Beispiel #1
0
 /**
  * Creates or force updates an unassigned node to the OFFLINE state for the specified region.
  *
  * <p>Attempts to create the node but if it exists will force it to transition to and OFFLINE
  * state.
  *
  * <p>Sets a watcher on the unassigned region node if the method is successful.
  *
  * <p>This method should be used when assigning a region.
  *
  * @param zkw zk reference
  * @param region region to be created as offline
  * @param serverName server event originates from
  * @throws KeeperException if unexpected zookeeper exception
  * @throws KeeperException.NodeExistsException if node already exists
  */
 public static boolean createOrForceNodeOffline(
     ZooKeeperWatcher zkw, HRegionInfo region, String serverName) throws KeeperException {
   LOG.debug(
       zkw.prefix(
           "Creating (or updating) unassigned node for "
               + region.getEncodedName()
               + " with OFFLINE state"));
   RegionTransitionData data =
       new RegionTransitionData(EventType.M_ZK_REGION_OFFLINE, region.getRegionName(), serverName);
   synchronized (zkw.getNodes()) {
     String node = getNodeName(zkw, region.getEncodedName());
     zkw.sync(node);
     zkw.getNodes().add(node);
     int version = ZKUtil.checkExists(zkw, node);
     if (version == -1) {
       ZKUtil.createAndWatch(zkw, node, data.getBytes());
     } else {
       if (!ZKUtil.setData(zkw, node, data.getBytes(), version)) {
         return false;
       } else {
         // We successfully forced to OFFLINE, reset watch and handle if
         // the state changed in between our set and the watch
         RegionTransitionData curData = ZKAssign.getData(zkw, region.getEncodedName());
         if (curData.getEventType() != data.getEventType()) {
           // state changed, need to process
           return false;
         }
       }
     }
   }
   return true;
 }
Beispiel #2
0
 public static void createNodeOffline(
     ZooKeeperWatcher zkw, HRegionInfo region, String serverName, final EventType event)
     throws KeeperException, KeeperException.NodeExistsException {
   LOG.debug(
       zkw.prefix(
           "Creating unassigned node for " + region.getEncodedName() + " in OFFLINE state"));
   RegionTransitionData data = new RegionTransitionData(event, region.getRegionName(), serverName);
   synchronized (zkw.getNodes()) {
     String node = getNodeName(zkw, region.getEncodedName());
     zkw.getNodes().add(node);
     ZKUtil.createAndWatch(zkw, node, data.getBytes());
   }
 }
Beispiel #3
0
 /**
  * Forces an existing unassigned node to the OFFLINE state for the specified region.
  *
  * <p>Does not create a new node. If a node does not already exist for this region, a {@link
  * NoNodeException} will be thrown.
  *
  * <p>Sets a watcher on the unassigned region node if the method is successful.
  *
  * <p>This method should only be used during recovery of regionserver failure.
  *
  * @param zkw zk reference
  * @param region region to be forced as offline
  * @param serverName server event originates from
  * @throws KeeperException if unexpected zookeeper exception
  * @throws KeeperException.NoNodeException if node does not exist
  */
 public static void forceNodeOffline(ZooKeeperWatcher zkw, HRegionInfo region, String serverName)
     throws KeeperException, KeeperException.NoNodeException {
   LOG.debug(
       zkw.prefix(
           "Forcing existing unassigned node for "
               + region.getEncodedName()
               + " to OFFLINE state"));
   RegionTransitionData data =
       new RegionTransitionData(EventType.M_ZK_REGION_OFFLINE, region.getRegionName(), serverName);
   synchronized (zkw.getNodes()) {
     String node = getNodeName(zkw, region.getEncodedName());
     zkw.getNodes().add(node);
     ZKUtil.setData(zkw, node, data.getBytes());
   }
 }
Beispiel #4
0
  /**
   * Creates a new unassigned node in the CLOSING state for the specified region.
   *
   * <p>Does not transition nodes from any states. If a node already exists for this region, a
   * {@link NodeExistsException} will be thrown.
   *
   * <p>If creation is successful, returns the version number of the CLOSING node created.
   *
   * <p>Does not set any watches.
   *
   * <p>This method should only be used by a RegionServer when initiating a close of a region after
   * receiving a CLOSE RPC from the Master.
   *
   * @param zkw zk reference
   * @param region region to be created as closing
   * @param serverName server event originates from
   * @return version of node after transition, -1 if unsuccessful transition
   * @throws KeeperException if unexpected zookeeper exception
   * @throws KeeperException.NodeExistsException if node already exists
   */
  public static int createNodeClosing(ZooKeeperWatcher zkw, HRegionInfo region, String serverName)
      throws KeeperException, KeeperException.NodeExistsException {
    LOG.debug(
        zkw.prefix(
            "Creating unassigned node for " + region.getEncodedName() + " in a CLOSING state"));

    RegionTransitionData data =
        new RegionTransitionData(
            EventType.RS_ZK_REGION_CLOSING, region.getRegionName(), serverName);

    synchronized (zkw.getNodes()) {
      String node = getNodeName(zkw, region.getEncodedName());
      zkw.getNodes().add(node);
      return ZKUtil.createAndWatch(zkw, node, data.getBytes());
    }
  }
Beispiel #5
0
 /**
  * Deletes an existing unassigned node that is in the specified state for the specified region.
  *
  * <p>If a node does not already exist for this region, a {@link NoNodeException} will be thrown.
  *
  * <p>No watcher is set whether this succeeds or not.
  *
  * <p>Returns false if the node was not in the proper state but did exist.
  *
  * <p>This method is used during table disables when a region finishes successfully closing. This
  * is the Master acknowledging completion of the specified regions transition to being closed.
  *
  * @param zkw zk reference
  * @param regionName region to be deleted from zk
  * @param expectedState state region must be in for delete to complete
  * @param expectedVersion of the znode that is to be deleted. If expectedVersion need not be
  *     compared while deleting the znode pass -1
  * @throws KeeperException if unexpected zookeeper exception
  * @throws KeeperException.NoNodeException if node does not exist
  */
 public static boolean deleteNode(
     ZooKeeperWatcher zkw, String regionName, EventType expectedState, int expectedVersion)
     throws KeeperException, KeeperException.NoNodeException {
   LOG.debug(
       zkw.prefix(
           "Deleting existing unassigned "
               + "node for "
               + regionName
               + " that is in expected state "
               + expectedState));
   String node = getNodeName(zkw, regionName);
   zkw.sync(node);
   Stat stat = new Stat();
   byte[] bytes = ZKUtil.getDataNoWatch(zkw, node, stat);
   if (bytes == null) {
     // If it came back null, node does not exist.
     throw KeeperException.create(Code.NONODE);
   }
   RegionTransitionData data = RegionTransitionData.fromBytes(bytes);
   if (!data.getEventType().equals(expectedState)) {
     LOG.warn(
         zkw.prefix(
             "Attempting to delete unassigned "
                 + "node "
                 + regionName
                 + " in "
                 + expectedState
                 + " state but node is in "
                 + data.getEventType()
                 + " state"));
     return false;
   }
   if (expectedVersion != -1 && stat.getVersion() != expectedVersion) {
     LOG.warn(
         "The node we are trying to delete is not the expected one. " + "Got a version mismatch");
     return false;
   }
   synchronized (zkw.getNodes()) {
     // TODO: Does this go here or only if we successfully delete node?
     zkw.getNodes().remove(node);
     if (!ZKUtil.deleteNode(zkw, node, stat.getVersion())) {
       LOG.warn(
           zkw.prefix(
               "Attempting to delete "
                   + "unassigned node in "
                   + expectedState
                   + " state but "
                   + "after verifying it was in OPENED state, we got a version mismatch"));
       return false;
     }
     LOG.debug(
         zkw.prefix(
             "Successfully deleted unassigned node for region "
                 + regionName
                 + " in expected state "
                 + expectedState));
     return true;
   }
 }
Beispiel #6
0
 /**
  * Creates an unassigned node in the OFFLINE state for the specified region.
  *
  * <p>Runs asynchronously. Depends on no pre-existing znode.
  *
  * <p>Sets a watcher on the unassigned region node.
  *
  * @param zkw zk reference
  * @param region region to be created as offline
  * @param serverName server event originates from
  * @param cb
  * @param ctx
  * @throws KeeperException if unexpected zookeeper exception
  * @throws KeeperException.NodeExistsException if node already exists
  */
 public static void asyncCreateNodeOffline(
     ZooKeeperWatcher zkw,
     HRegionInfo region,
     String serverName,
     final AsyncCallback.StringCallback cb,
     final Object ctx)
     throws KeeperException {
   LOG.debug(
       zkw.prefix(
           "Async create of unassigned node for "
               + region.getEncodedName()
               + " with OFFLINE state"));
   RegionTransitionData data =
       new RegionTransitionData(EventType.M_ZK_REGION_OFFLINE, region.getRegionName(), serverName);
   synchronized (zkw.getNodes()) {
     String node = getNodeName(zkw, region.getEncodedName());
     zkw.getNodes().add(node);
     ZKUtil.asyncCreate(zkw, node, data.getBytes(), cb, ctx);
   }
 }
 public void deleteMetaLocation(ZooKeeperWatcher zookeeper, int replicaId) throws KeeperException {
   if (replicaId == HRegionInfo.DEFAULT_REPLICA_ID) {
     LOG.info("Deleting hbase:meta region location in ZooKeeper");
   } else {
     LOG.info("Deleting hbase:meta for " + replicaId + " region location in ZooKeeper");
   }
   try {
     // Just delete the node.  Don't need any watches.
     ZKUtil.deleteNode(zookeeper, zookeeper.getZNodeForReplica(replicaId));
   } catch (KeeperException.NoNodeException nne) {
     // Has already been deleted
   }
 }
 /**
  * Sets the location of <code>hbase:meta</code> in ZooKeeper to the specified server address.
  *
  * @param zookeeper
  * @param serverName
  * @param replicaId
  * @param state
  * @throws KeeperException
  */
 public static void setMetaLocation(
     ZooKeeperWatcher zookeeper, ServerName serverName, int replicaId, RegionState.State state)
     throws KeeperException {
   LOG.info("Setting hbase:meta region location in ZooKeeper as " + serverName);
   // Make the MetaRegionServer pb and then get its bytes and save this as
   // the znode content.
   MetaRegionServer pbrsr =
       MetaRegionServer.newBuilder()
           .setServer(ProtobufUtil.toServerName(serverName))
           .setRpcVersion(HConstants.RPC_CURRENT_VERSION)
           .setState(state.convert())
           .build();
   byte[] data = ProtobufUtil.prependPBMagic(pbrsr.toByteArray());
   try {
     ZKUtil.setData(zookeeper, zookeeper.getZNodeForReplica(replicaId), data);
   } catch (KeeperException.NoNodeException nne) {
     if (replicaId == HRegionInfo.DEFAULT_REPLICA_ID) {
       LOG.debug("META region location doesn't exist, create it");
     } else {
       LOG.debug("META region location doesn't exist for replicaId " + replicaId + ", create it");
     }
     ZKUtil.createAndWatch(zookeeper, zookeeper.getZNodeForReplica(replicaId), data);
   }
 }
  /**
   * Wait until the primary meta region is available. Get the secondary locations as well but don't
   * block for those.
   *
   * @param zkw
   * @param timeout
   * @param conf
   * @return ServerName or null if we timed out.
   * @throws InterruptedException
   */
  public List<ServerName> blockUntilAvailable(
      final ZooKeeperWatcher zkw, final long timeout, Configuration conf)
      throws InterruptedException {
    int numReplicasConfigured = 1;
    try {
      List<String> metaReplicaNodes = zkw.getMetaReplicaNodes();
      numReplicasConfigured = metaReplicaNodes.size();
    } catch (KeeperException e) {
      LOG.warn("Got ZK exception " + e);
    }
    List<ServerName> servers = new ArrayList<ServerName>(numReplicasConfigured);
    ServerName server = blockUntilAvailable(zkw, timeout);
    if (server == null) return null;
    servers.add(server);

    for (int replicaId = 1; replicaId < numReplicasConfigured; replicaId++) {
      // return all replica locations for the meta
      servers.add(getMetaRegionLocation(zkw, replicaId));
    }
    return servers;
  }
Beispiel #10
0
  /**
   * Verifies that the specified region is in the specified state in ZooKeeper.
   *
   * <p>Returns true if region is in transition and in the specified state in ZooKeeper. Returns
   * false if the region does not exist in ZK or is in a different state.
   *
   * <p>Method synchronizes() with ZK so will yield an up-to-date result but is a slow read.
   *
   * @param zkw
   * @param region
   * @param expectedState
   * @return true if region exists and is in expected state
   */
  public static boolean verifyRegionState(
      ZooKeeperWatcher zkw, HRegionInfo region, EventType expectedState) throws KeeperException {
    String encoded = region.getEncodedName();

    String node = getNodeName(zkw, encoded);
    zkw.sync(node);

    // Read existing data of the node
    byte[] existingBytes = null;
    try {
      existingBytes = ZKUtil.getDataAndWatch(zkw, node);
    } catch (KeeperException.NoNodeException nne) {
      return false;
    } catch (KeeperException e) {
      throw e;
    }
    if (existingBytes == null) return false;
    RegionTransitionData existingData = RegionTransitionData.fromBytes(existingBytes);
    if (existingData.getEventType() == expectedState) {
      return true;
    }
    return false;
  }
Beispiel #11
0
 /**
  * Load the meta region state from the meta server ZNode.
  *
  * @param zkw
  * @param replicaId
  * @return regionstate
  * @throws KeeperException
  */
 public static RegionState getMetaRegionState(ZooKeeperWatcher zkw, int replicaId)
     throws KeeperException {
   RegionState.State state = RegionState.State.OPEN;
   ServerName serverName = null;
   try {
     byte[] data = ZKUtil.getData(zkw, zkw.getZNodeForReplica(replicaId));
     if (data != null && data.length > 0 && ProtobufUtil.isPBMagicPrefix(data)) {
       try {
         int prefixLen = ProtobufUtil.lengthOfPBMagic();
         ZooKeeperProtos.MetaRegionServer rl =
             ZooKeeperProtos.MetaRegionServer.PARSER.parseFrom(
                 data, prefixLen, data.length - prefixLen);
         if (rl.hasState()) {
           state = RegionState.State.convert(rl.getState());
         }
         HBaseProtos.ServerName sn = rl.getServer();
         serverName = ServerName.valueOf(sn.getHostName(), sn.getPort(), sn.getStartCode());
       } catch (InvalidProtocolBufferException e) {
         throw new DeserializationException("Unable to parse meta region location");
       }
     } else {
       // old style of meta region location?
       serverName = ServerName.parseFrom(data);
     }
   } catch (DeserializationException e) {
     throw ZKUtil.convert(e);
   } catch (InterruptedException e) {
     Thread.currentThread().interrupt();
   }
   if (serverName == null) {
     state = RegionState.State.OFFLINE;
   }
   return new RegionState(
       RegionReplicaUtil.getRegionInfoForReplica(HRegionInfo.FIRST_META_REGIONINFO, replicaId),
       state,
       serverName);
 }
Beispiel #12
0
  /**
   * Private method that actually performs unassigned node transitions.
   *
   * <p>Attempts to transition the unassigned node for the specified region from the expected state
   * to the state in the specified transition data.
   *
   * <p>Method first reads existing data and verifies it is in the expected state. If the node does
   * not exist or the node is not in the expected state, the method returns -1. If the transition is
   * successful, the version number of the node following the transition is returned.
   *
   * <p>If the read state is what is expected, it attempts to write the new state and data into the
   * node. When doing this, it includes the expected version (determined when the existing state was
   * verified) to ensure that only one transition is successful. If there is a version mismatch, the
   * method returns -1.
   *
   * <p>If the write is successful, no watch is set and the method returns true.
   *
   * @param zkw zk reference
   * @param region region to be transitioned to opened
   * @param serverName server event originates from
   * @param endState state to transition node to if all checks pass
   * @param beginState state the node must currently be in to do transition
   * @param expectedVersion expected version of data before modification, or -1
   * @return version of node after transition, -1 if unsuccessful transition
   * @throws KeeperException if unexpected zookeeper exception
   */
  public static int transitionNode(
      ZooKeeperWatcher zkw,
      HRegionInfo region,
      String serverName,
      EventType beginState,
      EventType endState,
      int expectedVersion)
      throws KeeperException {
    String encoded = region.getEncodedName();
    if (LOG.isDebugEnabled()) {
      LOG.debug(
          zkw.prefix(
              "Attempting to transition node "
                  + HRegionInfo.prettyPrint(encoded)
                  + " from "
                  + beginState.toString()
                  + " to "
                  + endState.toString()));
    }

    String node = getNodeName(zkw, encoded);
    zkw.sync(node);

    // Read existing data of the node
    Stat stat = new Stat();
    byte[] existingBytes = ZKUtil.getDataNoWatch(zkw, node, stat);
    if (existingBytes == null) {
      // Node no longer exists.  Return -1. It means unsuccessful transition.
      return -1;
    }
    RegionTransitionData existingData = RegionTransitionData.fromBytes(existingBytes);

    // Verify it is the expected version
    if (expectedVersion != -1 && stat.getVersion() != expectedVersion) {
      LOG.warn(
          zkw.prefix(
              "Attempt to transition the "
                  + "unassigned node for "
                  + encoded
                  + " from "
                  + beginState
                  + " to "
                  + endState
                  + " failed, "
                  + "the node existed but was version "
                  + stat.getVersion()
                  + " not the expected version "
                  + expectedVersion));
      return -1;
    }

    // Verify it is in expected state
    if (!existingData.getEventType().equals(beginState)) {
      LOG.warn(
          zkw.prefix(
              "Attempt to transition the "
                  + "unassigned node for "
                  + encoded
                  + " from "
                  + beginState
                  + " to "
                  + endState
                  + " failed, "
                  + "the node existed but was in the state "
                  + existingData.getEventType()
                  + " set by the server "
                  + existingData.getServerName()));
      return -1;
    }

    // Write new data, ensuring data has not changed since we last read it
    try {
      RegionTransitionData data =
          new RegionTransitionData(endState, region.getRegionName(), serverName);
      if (!ZKUtil.setData(zkw, node, data.getBytes(), stat.getVersion())) {
        LOG.warn(
            zkw.prefix(
                "Attempt to transition the "
                    + "unassigned node for "
                    + encoded
                    + " from "
                    + beginState
                    + " to "
                    + endState
                    + " failed, "
                    + "the node existed and was in the expected state but then when "
                    + "setting data we got a version mismatch"));
        return -1;
      }
      if (LOG.isDebugEnabled()) {
        LOG.debug(
            zkw.prefix(
                "Successfully transitioned node "
                    + encoded
                    + " from "
                    + beginState
                    + " to "
                    + endState));
      }
      return stat.getVersion() + 1;
    } catch (KeeperException.NoNodeException nne) {
      LOG.warn(
          zkw.prefix(
              "Attempt to transition the "
                  + "unassigned node for "
                  + encoded
                  + " from "
                  + beginState
                  + " to "
                  + endState
                  + " failed, "
                  + "the node existed and was in the expected state but then when "
                  + "setting data it no longer existed"));
      return -1;
    }
  }
Beispiel #13
0
 /**
  * Deletes all unassigned nodes regardless of their state.
  *
  * <p>No watchers are set.
  *
  * <p>This method is used by the Master during cluster startup to clear out any existing state
  * from other cluster runs.
  *
  * @param zkw zk reference
  * @throws KeeperException if unexpected zookeeper exception
  */
 public static void deleteAllNodes(ZooKeeperWatcher zkw) throws KeeperException {
   LOG.debug(zkw.prefix("Deleting any existing unassigned nodes"));
   ZKUtil.deleteChildrenRecursively(zkw, zkw.assignmentZNode);
 }