Beispiel #1
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 #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
 /**
  * Gets the current data in the unassigned node for the specified region name or fully-qualified
  * path.
  *
  * <p>Returns null if the region does not currently have a node.
  *
  * <p>Does not set a watch.
  *
  * @param zkw zk reference
  * @param pathOrRegionName fully-specified path or region name
  * @param stat object to store node info into on getData call
  * @return data for the unassigned node or null if node does not exist
  * @throws KeeperException if unexpected zookeeper exception
  */
 public static RegionTransitionData getDataNoWatch(
     ZooKeeperWatcher zkw, String pathOrRegionName, Stat stat) throws KeeperException {
   String node =
       pathOrRegionName.startsWith("/") ? pathOrRegionName : getNodeName(zkw, pathOrRegionName);
   byte[] data = ZKUtil.getDataNoWatch(zkw, node, stat);
   if (data == null) {
     return null;
   }
   return RegionTransitionData.fromBytes(data);
 }
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);
   }
 }
Beispiel #7
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 #8
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 #9
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;
    }
  }