/**
   * Creates the serialized value of the object and stores this in ZooKeeper under the path. It
   * updates the lastStatusVersion. It does not set a watcher for the path.
   */
  private void updateCoordinateData() throws CoordinateMissingException, CloudnameException {
    if (!started.get()) {
      throw new IllegalStateException("Not started.");
    }

    if (!zkClient.isConnected()) {
      throw new CloudnameException("No proper connection with zookeeper.");
    }

    synchronized (lastStatusVersionMonitor) {
      try {
        Stat stat =
            zkClient
                .getZookeeper()
                .setData(
                    path,
                    zkCoordinateData.snapshot().serialize().getBytes(Util.CHARSET_NAME),
                    lastStatusVersion);
        LOG.fine("Updated coordinate, latest version is " + stat.getVersion());
        lastStatusVersion = stat.getVersion();
      } catch (KeeperException.NoNodeException e) {
        throw new CoordinateMissingException("Coordinate does not exist " + path);
      } catch (KeeperException e) {
        throw new CloudnameException(
            "ZooKeeper errror in updateCoordinateData: " + e.getMessage(), e);
      } catch (UnsupportedEncodingException e) {
        throw new CloudnameException(e);
      } catch (InterruptedException e) {
        throw new CloudnameException(e);
      } catch (IOException e) {
        throw new CloudnameException(e);
      }
    }
  }
 private static boolean checkStale(SolrZkClient zkClient, String zkPath, int currentVersion) {
   if (zkPath == null) return false;
   try {
     Stat stat = zkClient.exists(zkPath, null, true);
     if (stat == null) {
       if (currentVersion > -1) return true;
       return false;
     }
     if (stat.getVersion() > currentVersion) {
       log.info(
           zkPath + " is stale will need an update from {} to {}",
           currentVersion,
           stat.getVersion());
       return true;
     }
     return false;
   } catch (KeeperException.NoNodeException nne) {
     // no problem
   } catch (KeeperException e) {
     log.error("error refreshing solrconfig ", e);
   } catch (InterruptedException e) {
     Thread.currentThread().isInterrupted();
   }
   return false;
 }
Beispiel #3
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;
   }
 }
  @Test
  public void testSyncGet() {
    String className = TestHelper.getTestClassName();
    String methodName = TestHelper.getTestMethodName();
    String testName = className + "_" + methodName;

    System.out.println("START " + testName + " at " + new Date(System.currentTimeMillis()));

    String path = String.format("/%s/%s", testName, "msg_0");
    ZNRecord record = new ZNRecord("msg_0");
    ZkBaseDataAccessor<ZNRecord> accessor = new ZkBaseDataAccessor<ZNRecord>(_gZkClient);

    Stat stat = new Stat();
    ZNRecord getRecord = accessor.get(path, stat, 0);
    Assert.assertNull(getRecord);

    try {
      accessor.get(path, stat, AccessOption.THROW_EXCEPTION_IFNOTEXIST);
      Assert.fail("Should throw exception if not exist");
    } catch (Exception e) {
      // OK
    }

    boolean success = accessor.create(path, record, AccessOption.PERSISTENT);
    Assert.assertTrue(success);

    getRecord = accessor.get(path, stat, 0);
    Assert.assertNotNull(getRecord);
    Assert.assertEquals(getRecord.getId(), "msg_0");
    Assert.assertEquals(stat.getVersion(), 0);

    record.setSimpleField("key0", "value0");
    success = accessor.set(path, record, AccessOption.PERSISTENT);
    Assert.assertTrue(success);

    getRecord = accessor.get(path, stat, 0);
    Assert.assertNotNull(getRecord);
    Assert.assertEquals(record.getSimpleFields().size(), 1);
    Assert.assertNotNull(getRecord.getSimpleField("key0"));
    Assert.assertEquals(getRecord.getSimpleField("key0"), "value0");
    Assert.assertEquals(stat.getVersion(), 1);

    ZNRecord newRecord = new ZNRecord("msg_0");
    newRecord.setSimpleField("key1", "value1");
    success = accessor.update(path, new ZNRecordUpdater(newRecord), AccessOption.PERSISTENT);
    Assert.assertTrue(success);

    getRecord = accessor.get(path, stat, 0);
    Assert.assertNotNull(getRecord);
    Assert.assertEquals(getRecord.getSimpleFields().size(), 2);
    Assert.assertNotNull(getRecord.getSimpleField("key0"));
    Assert.assertEquals(getRecord.getSimpleField("key0"), "value0");
    Assert.assertNotNull(getRecord.getSimpleField("key1"));
    Assert.assertEquals(getRecord.getSimpleField("key1"), "value1");
    Assert.assertEquals(stat.getVersion(), 2);

    System.out.println("END " + testName + " at " + new Date(System.currentTimeMillis()));
  }
Beispiel #5
0
  /**
   * Changes the shared value only if its value has not changed since this client last read it. If
   * the value has changed, the value is not set and this client's view of the value is updated.
   * i.e. if the value is not successful you can get the updated value by calling {@link
   * #getValue()}.
   *
   * @param newValue the new value to attempt
   * @return true if the change attempt was successful, false if not. If the change was not
   *     successful, {@link #getValue()} will return the updated value
   * @throws Exception ZK errors, interruptions, etc.
   */
  public boolean trySetValue(byte[] newValue) throws Exception {
    Preconditions.checkState(state.get() == State.STARTED, "not started");

    try {
      client.setData().withVersion(stat.getVersion()).forPath(path, newValue);
      stat.setVersion(stat.getVersion() + 1);
      value = Arrays.copyOf(newValue, newValue.length);
      return true;
    } catch (KeeperException.BadVersionException ignore) {
      // ignore
    }

    readValue();
    return false;
  }
  @Test
  public void testCheckVersion() throws Exception {
    CuratorFramework client =
        CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
    client.start();
    try {
      client.create().forPath("/foo");
      Stat stat = client.setData().forPath("/foo", "new".getBytes()); // up the version

      try {
        client
            .inTransaction()
            .check()
            .withVersion(stat.getVersion() + 1)
            .forPath("/foo") // force a bad version
            .and()
            .create()
            .forPath("/bar")
            .and()
            .commit();

        Assert.fail();
      } catch (KeeperException.BadVersionException correct) {
        // correct
      }

      Assert.assertNull(client.checkExists().forPath("/bar"));
    } finally {
      client.close();
    }
  }
  @Test
  public void testSyncGetStat() {
    String className = TestHelper.getTestClassName();
    String methodName = TestHelper.getTestMethodName();
    String testName = className + "_" + methodName;

    System.out.println("START " + testName + " at " + new Date(System.currentTimeMillis()));

    String path = String.format("/%s/%s", testName, "msg_0");
    ZNRecord record = new ZNRecord("msg_0");
    ZkBaseDataAccessor<ZNRecord> accessor = new ZkBaseDataAccessor<ZNRecord>(_gZkClient);

    Stat stat = accessor.getStat(path, 0);
    Assert.assertNull(stat);

    boolean success = accessor.create(path, record, AccessOption.EPHEMERAL);
    Assert.assertTrue(success);

    stat = accessor.getStat(path, 0);
    Assert.assertNotNull(stat);
    Assert.assertEquals(stat.getVersion(), 0);
    Assert.assertNotSame(stat.getEphemeralOwner(), 0);

    System.out.println("END " + testName + " at " + new Date(System.currentTimeMillis()));
  }
Beispiel #8
0
  /**
   * Change the shared value value irrespective of its previous state
   *
   * @param newValue new value
   * @throws Exception ZK errors, interruptions, etc.
   */
  public void setValue(byte[] newValue) throws Exception {
    Preconditions.checkState(state.get() == State.STARTED, "not started");

    client.setData().forPath(path, newValue);
    stat.setVersion(stat.getVersion() + 1);
    value = Arrays.copyOf(newValue, newValue.length);
  }
Beispiel #9
0
 public void updateRecord(MetaRecord rec) {
   try {
     long ts = System.currentTimeMillis();
     putRecord(rec, ts);
     String node = ZKUtil.joinZNode(H2MetaTableTracker.NODE_NAME, Integer.toString(rec.getId()));
     // setData会异步触发所有机器(包括本机)上的H2MetaTableTracker.nodeDataChanged
     // 然后触发下列调用:
     // =>org.h2.engine.Database.updateDatabaseObject(int)
     //  =>org.h2.engine.Database.update(Session, DbObject)
     //      =>org.h2.engine.Database.addMeta0(Session, DbObject, boolean)
     //          =>又到此方法
     // 所以会造成循环
     synchronized (this) { // 避免setData后立刻触发nodeDataChanged,此时IdVersion还未更新
       ZKUtil.setData(watcher, node, Bytes.toBytes(ts));
       // setData后watch不见了,所以要继续watch,监听其他人对此node的修改
       // ZKUtil.watchAndCheckExists(watcher, node);
       Stat stat = new Stat();
       ZKUtil.getDataAndWatch(watcher, node, stat);
       // 这里记录下id的最新版本,触发nodeDataChanged时再检查一下是否版本一样,
       // 如果不大于这里的版本那么就不再执行updateDatabaseObject操作
       tracker.updateIdVersion(rec.getId(), stat.getVersion());
     }
   } catch (Exception e) {
     throw new RuntimeException(e);
   }
 }
  /**
   * Try to atomically update a node in ZooKeeper, creating it if it doesn't exist. This is meant to
   * be used within an optimistic concurrency model.
   *
   * @param pathSuffix suffix to use to build path in ZooKeeper.
   * @param f function used to initialize the node, or transform the data already there.
   * @return true if node was created/updated, false if a concurrent modification occurred and
   *     succeeded while trying to update/create the node.
   * @throws Exception
   */
  private boolean tryAtomicUpdate(final String pathSuffix, final NodeFunction f) throws Exception {
    final String path = buildZookeeperPath(pathSuffix);
    final Stat stat = zk.checkExists().forPath(path);

    if (stat == null) {
      try {
        zk.create()
            .creatingParentsIfNeeded()
            .withMode(CreateMode.PERSISTENT)
            .forPath(path, f.initialize());
      } catch (KeeperException.NodeExistsException e) {
        LOG.debug("Concurrent creation of " + path + ", retrying", e);
        return false;
      }
    } else {
      Mod<byte[]> newVal = f.apply(zk.getData().forPath(path));

      if (newVal.hasModification()) {
        try {
          zk.setData().withVersion(stat.getVersion()).forPath(path, newVal.get());
        } catch (KeeperException.BadVersionException e) {
          LOG.debug("Concurrent update to " + path + ", retrying.", e);
          return false;
        }
      }
    }

    return true;
  }
Beispiel #11
0
 void trigeWatcher() {
   try {
     Stat s = zk.exists("/root", false); // 此处不设置watcher
     zk.setData("/root", "a".getBytes(), s.getVersion()); // 修改数据时需要提供version,version设为-1表示强制修改
   } catch (Exception e) {
     e.printStackTrace();
   }
 }
  protected Stat setData(String path, byte[] data, Stat stat) {

    try {
      stat = zooKeeper.setData(path, data, stat.getVersion());
    } catch (Exception e) {
      System.out.println("Exception caught in zk.setData(): " + e);
    }

    return stat;
  }
Beispiel #13
0
  /**
   * sync update
   *
   * @return: updatedData on success, or null on fail
   */
  public T update(
      String path, DataUpdater<T> updater, List<String> createPaths, Stat stat, int options) {
    CreateMode mode = AccessOption.getMode(options);
    if (mode == null) {
      LOG.error("Invalid update mode. options: " + options);
      return null;
    }

    boolean retry;
    T updatedData = null;
    do {
      retry = false;
      try {
        Stat readStat = new Stat();
        T oldData = (T) _zkClient.readData(path, readStat);
        T newData = updater.update(oldData);
        Stat setStat = _zkClient.writeDataGetStat(path, newData, readStat.getVersion());
        if (stat != null) {
          DataTree.copyStat(setStat, stat);
        }

        updatedData = newData;
      } catch (ZkBadVersionException e) {
        retry = true;
      } catch (ZkNoNodeException e) {
        // node not exist, try create
        try {
          T newData = updater.update(null);
          RetCode rc = create(path, newData, createPaths, options);
          switch (rc) {
            case OK:
              updatedData = newData;
              break;
            case NODE_EXISTS:
              retry = true;
              break;
            default:
              LOG.error("Fail to update path by creating: " + path);
              return null;
          }
        } catch (Exception e1) {
          LOG.error("Exception while updating path by creating: " + path, e1);
          return null;
        }
      } catch (Exception e) {
        LOG.error("Exception while updating path: " + path, e);
        return null;
      }
    } while (retry);

    return updatedData;
  }
Beispiel #14
0
 @PUT
 @Path("blueprint/{name}")
 public Response updateBlueprint(
     @Context UriInfo uri, @PathParam("name") String oldName, ConfigManifest blueprint) {
   Response res;
   try {
     ZooKeeper zk = Controller.getInstance().getZKInstance();
     String newName = oldName;
     if (blueprint.getUrl() != null) {
       newName = ZookeeperUtil.getBaseURL(blueprint.getUrl().toString());
     } else {
       blueprint.setUrl(uri.getAbsolutePath().toURL());
     }
     byte[] data = JAXBUtil.write(blueprint);
     Stat stat =
         zk.exists(
             CommonConfigurationKeys.ZOOKEEPER_CONFIG_BLUEPRINT_PATH_DEFAULT + '/' + newName,
             false);
     if (stat != null && oldName.equals(newName)) {
       // Update existing blueprint
       String path =
           CommonConfigurationKeys.ZOOKEEPER_CONFIG_BLUEPRINT_PATH_DEFAULT + '/' + oldName;
       zk.delete(path, stat.getVersion());
       zk.create(
           CommonConfigurationKeys.ZOOKEEPER_CONFIG_BLUEPRINT_PATH_DEFAULT + '/' + newName,
           data,
           Ids.OPEN_ACL_UNSAFE,
           CreateMode.PERSISTENT);
     } else if (stat != null) {
       // Conflict in name change
       throw new WebApplicationException(409);
     } else {
       // Create new blueprint
       try {
         zk.create(
             CommonConfigurationKeys.ZOOKEEPER_CONFIG_BLUEPRINT_PATH_DEFAULT + '/' + newName,
             data,
             Ids.OPEN_ACL_UNSAFE,
             CreateMode.PERSISTENT);
       } catch (KeeperException.NodeExistsException e) {
         throw new WebApplicationException(409);
       }
     }
     res = Response.noContent().build();
     return res;
   } catch (WebApplicationException e) {
     throw e;
   } catch (Exception e) {
     LOG.error(ExceptionUtil.getStackTrace(e));
     throw new WebApplicationException(500);
   }
 }
Beispiel #15
0
 public static void copyStat(Stat from, Stat to) {
   to.setAversion(from.getAversion());
   to.setCtime(from.getCtime());
   to.setCversion(from.getCversion());
   to.setCzxid(from.getCzxid());
   to.setMtime(from.getMtime());
   to.setMzxid(from.getMzxid());
   to.setPzxid(from.getPzxid());
   to.setVersion(from.getVersion());
   to.setEphemeralOwner(from.getEphemeralOwner());
   to.setDataLength(from.getDataLength());
   to.setNumChildren(from.getNumChildren());
 }
Beispiel #16
0
  public Integer getVersion(CuratorFramework zk, String path, boolean watch) throws Exception {
    String npath = PathUtils.normalize_path(path);
    Stat stat = null;
    if (existsNode(zk, npath, watch)) {
      if (watch) {
        stat = zk.checkExists().watched().forPath(PathUtils.normalize_path(path));
      } else {
        stat = zk.checkExists().forPath(PathUtils.normalize_path(path));
      }
      return Integer.valueOf(stat.getVersion());
    }

    return null;
  }
Beispiel #17
0
 @DELETE
 @Path("blueprint/{name}")
 public Response deleteStack(@PathParam("name") String name) {
   ZooKeeper zk = Controller.getInstance().getZKInstance();
   try {
     String path = ZookeeperUtil.getConfigManifestPath(name);
     Stat current = zk.exists(path, false);
     zk.delete(path, current.getVersion());
   } catch (Exception e) {
     LOG.error(ExceptionUtil.getStackTrace(e));
     throw new WebApplicationException(500);
   }
   Response res = Response.noContent().build();
   return res;
 }
  @Test(timeout = 60000)
  public void testBadVersionOnTwoAllocators() throws Exception {
    String allocationPath = "/allocation-bad-version";
    zkc.get()
        .create(allocationPath, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    Stat stat = new Stat();
    byte[] data = zkc.get().getData(allocationPath, false, stat);
    Versioned<byte[]> allocationData =
        new Versioned<byte[]>(data, new ZkVersion(stat.getVersion()));

    SimpleLedgerAllocator allocator1 =
        new SimpleLedgerAllocator(
            allocationPath, allocationData, newQuorumConfigProvider(dlConf), zkc, bkc);
    SimpleLedgerAllocator allocator2 =
        new SimpleLedgerAllocator(
            allocationPath, allocationData, newQuorumConfigProvider(dlConf), zkc, bkc);
    allocator1.allocate();
    // wait until allocated
    ZKTransaction txn1 = newTxn();
    LedgerHandle lh = FutureUtils.result(allocator1.tryObtain(txn1, NULL_LISTENER));
    allocator2.allocate();
    ZKTransaction txn2 = newTxn();
    try {
      FutureUtils.result(allocator2.tryObtain(txn2, NULL_LISTENER));
      fail(
          "Should fail allocating on second allocator as allocator1 is starting allocating something.");
    } catch (ZKException zke) {
      assertEquals(KeeperException.Code.BADVERSION, zke.getKeeperExceptionCode());
    }
    FutureUtils.result(txn1.execute());
    Utils.close(allocator1);
    Utils.close(allocator2);

    long eid = lh.addEntry("hello world".getBytes());
    lh.close();
    LedgerHandle readLh =
        bkc.get()
            .openLedger(lh.getId(), BookKeeper.DigestType.CRC32, dlConf.getBKDigestPW().getBytes());
    Enumeration<LedgerEntry> entries = readLh.readEntries(eid, eid);
    int i = 0;
    while (entries.hasMoreElements()) {
      LedgerEntry entry = entries.nextElement();
      assertEquals("hello world", new String(entry.getEntry(), UTF_8));
      ++i;
    }
    assertEquals(1, i);
  }
 /**
  * Atomically sets the value to the given updated value if the current value {@code ==} the
  * expected value. Remember to always check {@link AtomicValue#succeeded()}.
  *
  * @param expectedValue the expected value
  * @param newValue the new value
  * @return value info
  * @throws Exception ZooKeeper errors
  */
 public AtomicValue<byte[]> compareAndSet(byte[] expectedValue, byte[] newValue) throws Exception {
   Stat stat = new Stat();
   MutableAtomicValue<byte[]> result = new MutableAtomicValue<byte[]>(null, null, false);
   boolean createIt = getCurrentValue(result, stat);
   if (!createIt && Arrays.equals(expectedValue, result.preValue)) {
     try {
       client.setData().withVersion(stat.getVersion()).forPath(path, newValue);
       result.succeeded = true;
       result.postValue = newValue;
     } catch (KeeperException.BadVersionException dummy) {
       result.succeeded = false;
     } catch (KeeperException.NoNodeException dummy) {
       result.succeeded = false;
     }
   } else {
     result.succeeded = false;
   }
   return result;
 }
 /**
  * Try to own the task by transitioning the zk node data from UNASSIGNED to OWNED.
  *
  * <p>This method is also used to periodically heartbeat the task progress by transitioning the
  * node from OWNED to OWNED.
  *
  * <p>
  *
  * @param isFirstTime shows whther it's the first attempt.
  * @param zkw zk wathcer
  * @param server name
  * @param task to own
  * @param taskZKVersion version of the task in zk
  * @return non-negative integer value when task can be owned by current region server otherwise -1
  */
 protected static int attemptToOwnTask(
     boolean isFirstTime,
     ZooKeeperWatcher zkw,
     ServerName server,
     String task,
     RecoveryMode mode,
     int taskZKVersion) {
   int latestZKVersion = FAILED_TO_OWN_TASK;
   try {
     SplitLogTask slt = new SplitLogTask.Owned(server, mode);
     Stat stat = zkw.getRecoverableZooKeeper().setData(task, slt.toByteArray(), taskZKVersion);
     if (stat == null) {
       LOG.warn("zk.setData() returned null for path " + task);
       SplitLogCounters.tot_wkr_task_heartbeat_failed.incrementAndGet();
       return FAILED_TO_OWN_TASK;
     }
     latestZKVersion = stat.getVersion();
     SplitLogCounters.tot_wkr_task_heartbeat.incrementAndGet();
     return latestZKVersion;
   } catch (KeeperException e) {
     if (!isFirstTime) {
       if (e.code().equals(KeeperException.Code.NONODE)) {
         LOG.warn("NONODE failed to assert ownership for " + task, e);
       } else if (e.code().equals(KeeperException.Code.BADVERSION)) {
         LOG.warn("BADVERSION failed to assert ownership for " + task, e);
       } else {
         LOG.warn("failed to assert ownership for " + task, e);
       }
     }
   } catch (InterruptedException e1) {
     LOG.warn(
         "Interrupted while trying to assert ownership of "
             + task
             + " "
             + StringUtils.stringifyException(e1));
     Thread.currentThread().interrupt();
   }
   SplitLogCounters.tot_wkr_task_heartbeat_failed.incrementAndGet();
   return FAILED_TO_OWN_TASK;
 }
 public void write(String path, String value) throws InterruptedException, KeeperException {
   int retries = 0;
   while (true) {
     try {
       Stat stat = zk.exists(path, false);
       if (stat == null) {
         zk.create(path, value.getBytes(CHARSET), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
       } else {
         zk.setData(path, value.getBytes(CHARSET), stat.getVersion());
       }
       return;
     } catch (KeeperException.SessionExpiredException e) {
       throw e;
     } catch (KeeperException e) {
       if (retries++ == MAX_RETRIES) {
         throw e;
       }
       // sleep then retry
       TimeUnit.SECONDS.sleep(RETRY_PERIOD_SECONDS);
     }
   }
 }
 /** @see org.storevm.toolkits.session.zookeeper.handler.GetDataHandler#handle() */
 @SuppressWarnings("unchecked")
 @Override
 public <T> T handle() throws Exception {
   if (zookeeper != null) {
     String path = GROUP_NAME + NODE_SEP + id;
     // 检查指定的Session节点是否存在
     Stat stat = zookeeper.exists(path, false);
     // 如果节点存在则删除之
     if (stat != null) {
       // 查找数据节点是否存在,不存在就创建一个
       String dataPath = path + NODE_SEP + key;
       stat = zookeeper.exists(dataPath, false);
       if (stat == null) {
         // 创建数据节点
         zookeeper.create(dataPath, null, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
         if (LOGGER.isInfoEnabled()) {
           LOGGER.info("创建数据节点完成[" + dataPath + "]");
         }
       }
       // 在节点上设置数据,所有数据必须可序列化
       if (data instanceof Serializable) {
         int dataNodeVer = -1;
         if (stat != null) {
           // 记录数据节点的版本
           dataNodeVer = stat.getVersion();
         }
         byte[] arrData = SerializationUtils.serialize(data);
         stat = zookeeper.setData(dataPath, arrData, dataNodeVer);
         if (LOGGER.isInfoEnabled()) {
           LOGGER.info("更新数据节点数据完成[" + dataPath + "][" + data + "]");
         }
         return (T) Boolean.TRUE;
       }
     }
   }
   return (T) Boolean.FALSE;
 }
  private boolean tryOnce(MutableAtomicValue<byte[]> result, MakeValue makeValue) throws Exception {
    Stat stat = new Stat();
    boolean createIt = getCurrentValue(result, stat);

    boolean success = false;
    try {
      byte[] newValue = makeValue.makeFrom(result.preValue);
      if (createIt) {
        client.create().forPath(path, newValue);
      } else {
        client.setData().withVersion(stat.getVersion()).forPath(path, newValue);
      }
      result.postValue = Arrays.copyOf(newValue, newValue.length);
      success = true;
    } catch (KeeperException.NodeExistsException e) {
      // do Retry
    } catch (KeeperException.BadVersionException e) {
      // do Retry
    } catch (KeeperException.NoNodeException e) {
      // do Retry
    }

    return success;
  }
Beispiel #24
0
  public void consume() {
    while (true) {
      if (zooKeeper != null) {
        synchronized (mutex) {
          try {
            List<String> children = zooKeeper.getChildren(root, true);
            if (children.size() == 0) {
              mutex.wait();
            } else {
              Stat stat = new Stat();
              String minElement = root + "/" + min(children);

              String value = new String(zooKeeper.getData(minElement, false, stat));
              System.out.println(value);

              zooKeeper.delete(minElement, stat.getVersion());
            }
          } catch (KeeperException | InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }
  }
Beispiel #25
0
  @Test
  public void testBasicFunctionality() throws Exception {

    // Check ZNode for timestamp exists (storage instantiation should create it)
    Stat zNodeStats = zkClient.checkExists().forPath(TIMESTAMP_ZNODE);
    assertEquals(zNodeStats.getVersion(), 0);

    // Initial checks
    assertEquals(storage.getMaxTimestamp(), INITIAL_MAX_TS_VALUE);
    byte[] data = zkClient.getData().forPath(TIMESTAMP_ZNODE);
    assertEquals(data.length, BYTES_IN_LONG);

    // Check new timestamp does not allow negative values...
    try {
      storage.updateMaxTimestamp(INITIAL_MAX_TS_VALUE, NEGATIVE_TS);
      fail();
    } catch (IllegalArgumentException e) {
      LOG.info("Expected exception", e);
    }

    // ...nor is less than previous timestamp
    try {
      storage.updateMaxTimestamp(1, 0);
      fail();
    } catch (IllegalArgumentException e) {
      LOG.info("Expected exception", e);
    }

    // Check that the original version is still there
    zNodeStats = zkClient.checkExists().forPath(TIMESTAMP_ZNODE);
    assertEquals(zNodeStats.getVersion(), 0);

    // Iterate updating the timestamp and check the final value
    long previousMaxTimestamp = INITIAL_MAX_TS_VALUE;
    for (int i = 0; i < ITERATION_COUNT; i++) {
      long newMaxTimestamp = previousMaxTimestamp + 1_000_000;
      storage.updateMaxTimestamp(previousMaxTimestamp, newMaxTimestamp);
      previousMaxTimestamp = newMaxTimestamp;
    }
    assertEquals(storage.getMaxTimestamp(), 1_000_000 * ITERATION_COUNT);
    // Check the znode version has changed accordingly
    zNodeStats = zkClient.checkExists().forPath(TIMESTAMP_ZNODE);
    assertEquals(zNodeStats.getVersion(), ITERATION_COUNT);

    // Check exceptions
    doThrow(new RuntimeException()).when(storageInternalZKClient).getData();
    try {
      storage.getMaxTimestamp();
      fail();
    } catch (IOException e) {
      LOG.info("Expected exception", e);
    }

    doThrow(new RuntimeException()).when(storageInternalZKClient).setData();
    try {
      storage.updateMaxTimestamp(INITIAL_MAX_TS_VALUE, INITIAL_MAX_TS_VALUE + 1_000_000);
      fail();
    } catch (IOException e) {
      LOG.info("Expected exception", e);
    }

    // Reset the mock and double-check last result
    Mockito.reset(storageInternalZKClient);
    assertEquals(storage.getMaxTimestamp(), 1_000_000 * ITERATION_COUNT);

    // Finally check the znode version is still the same
    zNodeStats = zkClient.checkExists().forPath(TIMESTAMP_ZNODE);
    assertEquals(zNodeStats.getVersion(), ITERATION_COUNT);
  }
  @Test
  public void testShouldNotCompeleteOpenedEntityGroupSuccessfullyIfVersionMismatches()
      throws Exception {
    EntityGroup entityGroup = null;
    try {
      int testIndex = 0;
      TEST_UTIL.getHBaseTestingUtility().startMiniZKCluster();
      TEST_UTIL
          .getConfiguration()
          .set(
              FConstants.ZOOKEEPER_QUORUM,
              TEST_UTIL.getConfiguration().get(HConstants.ZOOKEEPER_QUORUM));
      TEST_UTIL
          .getConfiguration()
          .set(
              FConstants.ZOOKEEPER_CLIENT_PORT,
              TEST_UTIL.getConfiguration().get(HConstants.ZOOKEEPER_CLIENT_PORT));
      final Server server = new MockServer(TEST_UTIL);
      FTable htd =
          FMetaTestUtil.makeTable(
              "testShouldNotCompeleteOpenedEntityGroupSuccessfullyIfVersionMismatches");
      EntityGroupInfo egi =
          new EntityGroupInfo(
              Bytes.toBytes(htd.getTableName()),
              Bytes.toBytes(testIndex),
              Bytes.toBytes(testIndex + 1));
      entityGroup = EntityGroup.createEntityGroup(egi, TEST_UTIL.getConfiguration(), htd, null);
      assertNotNull(entityGroup);
      AssignmentManager am = Mockito.mock(AssignmentManager.class);
      EntityGroupStates rsm = Mockito.mock(EntityGroupStates.class);
      Mockito.doReturn(rsm).when(am).getEntityGroupStates();
      when(rsm.isEntityGroupInTransition(egi)).thenReturn(false);
      when(rsm.getEntityGroupState(egi))
          .thenReturn(
              new EntityGroupState(
                  entityGroup.getEntityGroupInfo(),
                  EntityGroupState.State.OPEN,
                  System.currentTimeMillis(),
                  server.getServerName()));
      // create a node with OPENED state
      zkw =
          WaspTestingUtility.createAndForceNodeToOpenedState(
              TEST_UTIL, entityGroup, server.getServerName());
      when(am.getZKTable()).thenReturn(new ZKTable(zkw));
      Stat stat = new Stat();
      String nodeName =
          ZKAssign.getNodeName(zkw, entityGroup.getEntityGroupInfo().getEncodedName());
      ZKUtil.getDataAndWatch(zkw, nodeName, stat);

      // use the version for the OpenedEntityGroupHandler
      OpenedEntityGroupHandler handler =
          new OpenedEntityGroupHandler(
              server,
              am,
              entityGroup.getEntityGroupInfo(),
              server.getServerName(),
              stat.getVersion());
      // Once again overwrite the same znode so that the version changes.
      ZKAssign.transitionNode(
          zkw,
          entityGroup.getEntityGroupInfo(),
          server.getServerName(),
          EventType.FSERVER_ZK_ENTITYGROUP_OPENED,
          EventType.FSERVER_ZK_ENTITYGROUP_OPENED,
          stat.getVersion());

      // Should not invoke assignmentmanager.entityGroupOnline. If it is
      // invoked as per current mocking it will throw null pointer exception.
      boolean expectedException = false;
      try {
        handler.process();
      } catch (Exception e) {
        expectedException = true;
      }
      assertFalse("The process method should not throw any exception.", expectedException);
      List<String> znodes = ZKUtil.listChildrenAndWatchForNewChildren(zkw, zkw.assignmentZNode);
      String entityGroupName = znodes.get(0);
      assertEquals(
          "The entityGroup should not be opened successfully.",
          entityGroupName,
          entityGroup.getEntityGroupInfo().getEncodedName());
    } finally {
      EntityGroup.closeEntityGroup(entityGroup);
      TEST_UTIL.getHBaseTestingUtility().shutdownMiniZKCluster();
    }
  }
  /**
   * try to grab a 'lock' on the task zk node to own and execute the task.
   *
   * <p>
   *
   * @param path zk node for the task
   */
  private void grabTask(String path) {
    Stat stat = new Stat();
    byte[] data;
    synchronized (grabTaskLock) {
      currentTask = path;
      workerInGrabTask = true;
      if (Thread.interrupted()) {
        return;
      }
    }
    try {
      try {
        if ((data = ZKUtil.getDataNoWatch(watcher, path, stat)) == null) {
          SplitLogCounters.tot_wkr_failed_to_grab_task_no_data.incrementAndGet();
          return;
        }
      } catch (KeeperException e) {
        LOG.warn("Failed to get data for znode " + path, e);
        SplitLogCounters.tot_wkr_failed_to_grab_task_exception.incrementAndGet();
        return;
      }
      SplitLogTask slt;
      try {
        slt = SplitLogTask.parseFrom(data);
      } catch (DeserializationException e) {
        LOG.warn("Failed parse data for znode " + path, e);
        SplitLogCounters.tot_wkr_failed_to_grab_task_exception.incrementAndGet();
        return;
      }
      if (!slt.isUnassigned()) {
        SplitLogCounters.tot_wkr_failed_to_grab_task_owned.incrementAndGet();
        return;
      }

      currentVersion =
          attemptToOwnTask(
              true, watcher, server.getServerName(), path, slt.getMode(), stat.getVersion());
      if (currentVersion < 0) {
        SplitLogCounters.tot_wkr_failed_to_grab_task_lost_race.incrementAndGet();
        return;
      }

      if (ZKSplitLog.isRescanNode(watcher, currentTask)) {
        ZkSplitLogWorkerCoordination.ZkSplitTaskDetails splitTaskDetails =
            new ZkSplitLogWorkerCoordination.ZkSplitTaskDetails();
        splitTaskDetails.setTaskNode(currentTask);
        splitTaskDetails.setCurTaskZKVersion(new MutableInt(currentVersion));

        endTask(
            new SplitLogTask.Done(server.getServerName(), slt.getMode()),
            SplitLogCounters.tot_wkr_task_acquired_rescan,
            splitTaskDetails);
        return;
      }

      LOG.info("worker " + server.getServerName() + " acquired task " + path);
      SplitLogCounters.tot_wkr_task_acquired.incrementAndGet();
      getDataSetWatchAsync();

      submitTask(path, slt.getMode(), currentVersion, reportPeriod);

      // after a successful submit, sleep a little bit to allow other RSs to grab the rest tasks
      try {
        int sleepTime = RandomUtils.nextInt(500) + 500;
        Thread.sleep(sleepTime);
      } catch (InterruptedException e) {
        LOG.warn("Interrupted while yielding for other region servers", e);
        Thread.currentThread().interrupt();
      }
    } finally {
      synchronized (grabTaskLock) {
        workerInGrabTask = false;
        // clear the interrupt from stopTask() otherwise the next task will
        // suffer
        Thread.interrupted();
      }
    }
  }
Beispiel #28
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;
    }
  }
 /**
  * Allows you to do
  *
  * <pre><code>node.data = "some data: ${var}"</code></pre>
  *
  * in Groovy code.
  *
  * @param data
  * @throws InterruptedException
  * @throws KeeperException
  */
 public void setData(Object data) throws InterruptedException, KeeperException {
   zookeeper.setData(path, serialize(data), stat.getVersion());
 }
  @Test(timeout = 60000)
  public void testSuccessAllocatorShouldDeleteUnusedledger() throws Exception {
    String allocationPath = "/allocation-delete-unused-ledger";
    zkc.get()
        .create(allocationPath, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    Stat stat = new Stat();
    byte[] data = zkc.get().getData(allocationPath, false, stat);

    Versioned<byte[]> allocationData =
        new Versioned<byte[]>(data, new ZkVersion(stat.getVersion()));

    SimpleLedgerAllocator allocator1 =
        new SimpleLedgerAllocator(
            allocationPath, allocationData, newQuorumConfigProvider(dlConf), zkc, bkc);
    allocator1.allocate();
    // wait until allocated
    ZKTransaction txn1 = newTxn();
    LedgerHandle lh1 = FutureUtils.result(allocator1.tryObtain(txn1, NULL_LISTENER));

    // Second allocator kicks in
    stat = new Stat();
    data = zkc.get().getData(allocationPath, false, stat);
    allocationData = new Versioned<byte[]>(data, new ZkVersion(stat.getVersion()));
    SimpleLedgerAllocator allocator2 =
        new SimpleLedgerAllocator(
            allocationPath, allocationData, newQuorumConfigProvider(dlConf), zkc, bkc);
    allocator2.allocate();
    // wait until allocated
    ZKTransaction txn2 = newTxn();
    LedgerHandle lh2 = FutureUtils.result(allocator2.tryObtain(txn2, NULL_LISTENER));

    // should fail to commit txn1 as version is changed by second allocator
    try {
      FutureUtils.result(txn1.execute());
      fail(
          "Should fail commit obtaining ledger handle from first allocator as allocator is modified by second allocator.");
    } catch (ZKException ke) {
      // as expected
    }
    FutureUtils.result(txn2.execute());
    Utils.close(allocator1);
    Utils.close(allocator2);

    // ledger handle should be deleted
    try {
      lh1.close();
      fail("LedgerHandle allocated by allocator1 should be deleted.");
    } catch (BKException bke) {
      // as expected
    }
    try {
      bkc.get()
          .openLedger(lh1.getId(), BookKeeper.DigestType.CRC32, dlConf.getBKDigestPW().getBytes());
      fail("LedgerHandle allocated by allocator1 should be deleted.");
    } catch (BKException.BKNoSuchLedgerExistsException nslee) {
      // as expected
    }
    long eid = lh2.addEntry("hello world".getBytes());
    lh2.close();
    LedgerHandle readLh =
        bkc.get()
            .openLedger(
                lh2.getId(), BookKeeper.DigestType.CRC32, dlConf.getBKDigestPW().getBytes());
    Enumeration<LedgerEntry> entries = readLh.readEntries(eid, eid);
    int i = 0;
    while (entries.hasMoreElements()) {
      LedgerEntry entry = entries.nextElement();
      assertEquals("hello world", new String(entry.getEntry(), UTF_8));
      ++i;
    }
    assertEquals(1, i);
  }