@Override public void setLastSequenceIds(String peerId, Map<String, Long> lastSeqIds) throws ReplicationException { try { // No need CAS and retry here, because it'll call setLastSequenceIds() for disabled peers // only, so no conflict happen. List<ZKUtilOp> listOfOps = new ArrayList<>(); for (Entry<String, Long> lastSeqEntry : lastSeqIds.entrySet()) { String path = getSerialReplicationRegionPeerNode(lastSeqEntry.getKey(), peerId); ZKUtil.createWithParents(zookeeper, path); listOfOps.add(ZKUtilOp.setData(path, ZKUtil.positionToByteArray(lastSeqEntry.getValue()))); } if (!listOfOps.isEmpty()) { ZKUtil.multiOrSequential(zookeeper, listOfOps, true); } } catch (KeeperException e) { throw new ReplicationException("Failed to set last sequence ids, peerId=" + peerId + ", size of lastSeqIds=" + lastSeqIds.size(), e); } }
private void addLastSeqIdsToOps(String queueId, Map<String, Long> lastSeqIds, List<ZKUtilOp> listOfOps) throws KeeperException, ReplicationException { String peerId = new ReplicationQueueInfo(queueId).getPeerId(); for (Entry<String, Long> lastSeqEntry : lastSeqIds.entrySet()) { String path = getSerialReplicationRegionPeerNode(lastSeqEntry.getKey(), peerId); Pair<Long, Integer> p = getLastSequenceIdWithVersion(lastSeqEntry.getKey(), peerId); byte[] data = ZKUtil.positionToByteArray(lastSeqEntry.getValue()); if (p.getSecond() < 0) { // ZNode does not exist. ZKUtil.createWithParents(zookeeper, path.substring(0, path.lastIndexOf(ZNodePaths.ZNODE_PATH_SEPARATOR))); listOfOps.add(ZKUtilOp.createAndFailSilent(path, data)); continue; } // Perform CAS in a specific version v0 (HBASE-20138) int v0 = p.getSecond(); long lastPushedSeqId = p.getFirst(); if (lastSeqEntry.getValue() <= lastPushedSeqId) { continue; } listOfOps.add(ZKUtilOp.setData(path, data, v0)); } }
@Override public void setWALPosition(ServerName serverName, String queueId, String fileName, long position, Map<String, Long> lastSeqIds) throws ReplicationException { try { for (int retry = 0;; retry++) { List<ZKUtilOp> listOfOps = new ArrayList<>(); if (position > 0) { listOfOps.add(ZKUtilOp.setData(getFileNode(serverName, queueId, fileName), ZKUtil.positionToByteArray(position))); } // Persist the max sequence id(s) of regions for serial replication atomically. addLastSeqIdsToOps(queueId, lastSeqIds, listOfOps); if (listOfOps.isEmpty()) { return; } try { ZKUtil.multiOrSequential(zookeeper, listOfOps, false); return; } catch (KeeperException.BadVersionException | KeeperException.NodeExistsException e) { LOG.warn( "Bad version(or node exist) when persist the last pushed sequence id to zookeeper storage, " + "Retry = " + retry + ", serverName=" + serverName + ", queueId=" + queueId + ", fileName=" + fileName); } } } catch (KeeperException e) { throw new ReplicationException("Failed to set log position (serverName=" + serverName + ", queueId=" + queueId + ", fileName=" + fileName + ", position=" + position + ")", e); } }
@Test public void testRunSequentialOnMultiFailure() throws Exception { String path1 = ZNodePaths.joinZNode(zkw.getZNodePaths().baseZNode, "runSequential1"); String path2 = ZNodePaths.joinZNode(zkw.getZNodePaths().baseZNode, "runSequential2"); String path3 = ZNodePaths.joinZNode(zkw.getZNodePaths().baseZNode, "runSequential3"); String path4 = ZNodePaths.joinZNode(zkw.getZNodePaths().baseZNode, "runSequential4"); // create some nodes that we will use later LinkedList<ZKUtilOp> ops = new LinkedList<>(); ops.add(ZKUtilOp.createAndFailSilent(path1, Bytes.toBytes(path1))); ops.add(ZKUtilOp.createAndFailSilent(path2, Bytes.toBytes(path2))); ZKUtil.multiOrSequential(zkw, ops, false); // test that, even with operations that fail, the ones that would pass will pass // with runSequentialOnMultiFailure ops = new LinkedList<>(); ops.add(ZKUtilOp.setData(path1, Bytes.add(Bytes.toBytes(path1), Bytes.toBytes(path1)))); // pass ops.add(ZKUtilOp.deleteNodeFailSilent(path2)); // pass ops.add(ZKUtilOp.deleteNodeFailSilent(path3)); // fail -- node doesn't exist ops.add(ZKUtilOp.createAndFailSilent(path4, Bytes.add(Bytes.toBytes(path4), Bytes.toBytes(path4)))); // pass ZKUtil.multiOrSequential(zkw, ops, true); assertTrue(Bytes.equals(ZKUtil.getData(zkw, path1), Bytes.add(Bytes.toBytes(path1), Bytes.toBytes(path1)))); assertTrue(ZKUtil.checkExists(zkw, path2) == -1); assertTrue(ZKUtil.checkExists(zkw, path3) == -1); assertFalse(ZKUtil.checkExists(zkw, path4) == -1); }
@Test public void testSimpleMulti() throws Exception { // null multi ZKUtil.multiOrSequential(zkw, null, false); // empty multi ZKUtil.multiOrSequential(zkw, new LinkedList<>(), false); // single create String path = ZNodePaths.joinZNode(zkw.getZNodePaths().baseZNode, "testSimpleMulti"); LinkedList<ZKUtilOp> singleCreate = new LinkedList<>(); singleCreate.add(ZKUtilOp.createAndFailSilent(path, new byte[0])); ZKUtil.multiOrSequential(zkw, singleCreate, false); assertTrue(ZKUtil.checkExists(zkw, path) != -1); // single setdata LinkedList<ZKUtilOp> singleSetData = new LinkedList<>(); byte [] data = Bytes.toBytes("foobar"); singleSetData.add(ZKUtilOp.setData(path, data)); ZKUtil.multiOrSequential(zkw, singleSetData, false); assertTrue(Bytes.equals(ZKUtil.getData(zkw, path), data)); // single delete LinkedList<ZKUtilOp> singleDelete = new LinkedList<>(); singleDelete.add(ZKUtilOp.deleteNodeFailSilent(path)); ZKUtil.multiOrSequential(zkw, singleDelete, false); assertTrue(ZKUtil.checkExists(zkw, path) == -1); }
@Test public void testSimpleMulti() throws Exception { // null multi ZKUtil.multiOrSequential(zkw, null, false); // empty multi ZKUtil.multiOrSequential(zkw, new LinkedList<>(), false); // single create String path = ZNodePaths.joinZNode(zkw.znodePaths.baseZNode, "testSimpleMulti"); LinkedList<ZKUtilOp> singleCreate = new LinkedList<>(); singleCreate.add(ZKUtilOp.createAndFailSilent(path, new byte[0])); ZKUtil.multiOrSequential(zkw, singleCreate, false); assertTrue(ZKUtil.checkExists(zkw, path) != -1); // single setdata LinkedList<ZKUtilOp> singleSetData = new LinkedList<>(); byte [] data = Bytes.toBytes("foobar"); singleSetData.add(ZKUtilOp.setData(path, data)); ZKUtil.multiOrSequential(zkw, singleSetData, false); assertTrue(Bytes.equals(ZKUtil.getData(zkw, path), data)); // single delete LinkedList<ZKUtilOp> singleDelete = new LinkedList<>(); singleDelete.add(ZKUtilOp.deleteNodeFailSilent(path)); ZKUtil.multiOrSequential(zkw, singleDelete, false); assertTrue(ZKUtil.checkExists(zkw, path) == -1); }
private void addLastSeqIdsToOps(String queueId, Map<String, Long> lastSeqIds, List<ZKUtilOp> listOfOps) throws KeeperException, ReplicationException { String peerId = new ReplicationQueueInfo(queueId).getPeerId(); for (Entry<String, Long> lastSeqEntry : lastSeqIds.entrySet()) { String path = getSerialReplicationRegionPeerNode(lastSeqEntry.getKey(), peerId); Pair<Long, Integer> p = getLastSequenceIdWithVersion(lastSeqEntry.getKey(), peerId); byte[] data = ZKUtil.positionToByteArray(lastSeqEntry.getValue()); if (p.getSecond() < 0) { // ZNode does not exist. ZKUtil.createWithParents(zookeeper, path.substring(0, path.lastIndexOf(ZNodePaths.ZNODE_PATH_SEPARATOR))); listOfOps.add(ZKUtilOp.createAndFailSilent(path, data)); continue; } // Perform CAS in a specific version v0 (HBASE-20138) int v0 = p.getSecond(); long lastPushedSeqId = p.getFirst(); if (lastSeqEntry.getValue() <= lastPushedSeqId) { continue; } listOfOps.add(ZKUtilOp.setData(path, data, v0)); } }
/** * Sets the data of the existing znode to be the specified data. The node * must exist but no checks are done on the existing data or version. * * <p>If the node does not exist, a {@link NoNodeException} will be thrown. * * <p>No watches are set but setting data will trigger other watchers of this * node. * * <p>If there is another problem, a KeeperException will be thrown. * * @param zkw zk reference * @param znode path of node * @param data data to set for node * @throws KeeperException if unexpected zookeeper exception */ public static void setData(ZooKeeperWatcher zkw, String znode, byte [] data) throws KeeperException, KeeperException.NoNodeException { setData(zkw, (SetData)ZKUtilOp.setData(znode, data)); }
@Override public void setLastSequenceIds(String peerId, Map<String, Long> lastSeqIds) throws ReplicationException { try { // No need CAS and retry here, because it'll call setLastSequenceIds() for disabled peers // only, so no conflict happen. List<ZKUtilOp> listOfOps = new ArrayList<>(); for (Entry<String, Long> lastSeqEntry : lastSeqIds.entrySet()) { String path = getSerialReplicationRegionPeerNode(lastSeqEntry.getKey(), peerId); ZKUtil.createWithParents(zookeeper, path); listOfOps.add(ZKUtilOp.setData(path, ZKUtil.positionToByteArray(lastSeqEntry.getValue()))); } if (!listOfOps.isEmpty()) { ZKUtil.multiOrSequential(zookeeper, listOfOps, true); } } catch (KeeperException e) { throw new ReplicationException("Failed to set last sequence ids, peerId=" + peerId + ", size of lastSeqIds=" + lastSeqIds.size(), e); } }
/** * Sets the data of the existing znode to be the specified data. The node * must exist but no checks are done on the existing data or version. * * <p>If the node does not exist, a {@link NoNodeException} will be thrown. * * <p>No watches are set but setting data will trigger other watchers of this * node. * * <p>If there is another problem, a KeeperException will be thrown. * * @param zkw zk reference * @param znode path of node * @param data data to set for node * @throws KeeperException if unexpected zookeeper exception */ public static void setData(ZooKeeperWatcher zkw, String znode, byte [] data) throws KeeperException, KeeperException.NoNodeException { setData(zkw, (SetData)ZKUtilOp.setData(znode, data)); }
/** * Sets the data of the existing znode to be the specified data. The node * must exist but no checks are done on the existing data or version. * * <p>If the node does not exist, a {@link NoNodeException} will be thrown. * * <p>No watches are set but setting data will trigger other watchers of this * node. * * <p>If there is another problem, a KeeperException will be thrown. * * @param zkw zk reference * @param znode path of node * @param data data to set for node * @throws KeeperException if unexpected zookeeper exception */ public static void setData(ZKWatcher zkw, String znode, byte [] data) throws KeeperException, KeeperException.NoNodeException { setData(zkw, (SetData)ZKUtilOp.setData(znode, data)); }
@Test public void testSetDataWithVersion() throws Exception { ZKUtil.createWithParents(ZKW, "/s1/s2/s3"); int v0 = getZNodeDataVersion("/s1/s2/s3"); assertEquals(0, v0); ZKUtil.setData(ZKW, "/s1/s2/s3", Bytes.toBytes(12L)); int v1 = getZNodeDataVersion("/s1/s2/s3"); assertEquals(1, v1); ZKUtil.multiOrSequential(ZKW, ImmutableList.of(ZKUtilOp.setData("/s1/s2/s3", Bytes.toBytes(13L), v1)), false); int v2 = getZNodeDataVersion("/s1/s2/s3"); assertEquals(2, v2); }
ops.add(ZKUtilOp.setData(path, Bytes.toBytes(path))); try { ZKUtil.multiOrSequential(zkw, ops, false);
@Test public void testRunSequentialOnMultiFailure() throws Exception { String path1 = ZNodePaths.joinZNode(zkw.getZNodePaths().baseZNode, "runSequential1"); String path2 = ZNodePaths.joinZNode(zkw.getZNodePaths().baseZNode, "runSequential2"); String path3 = ZNodePaths.joinZNode(zkw.getZNodePaths().baseZNode, "runSequential3"); String path4 = ZNodePaths.joinZNode(zkw.getZNodePaths().baseZNode, "runSequential4"); // create some nodes that we will use later LinkedList<ZKUtilOp> ops = new LinkedList<>(); ops.add(ZKUtilOp.createAndFailSilent(path1, Bytes.toBytes(path1))); ops.add(ZKUtilOp.createAndFailSilent(path2, Bytes.toBytes(path2))); ZKUtil.multiOrSequential(zkw, ops, false); // test that, even with operations that fail, the ones that would pass will pass // with runSequentialOnMultiFailure ops = new LinkedList<>(); ops.add(ZKUtilOp.setData(path1, Bytes.add(Bytes.toBytes(path1), Bytes.toBytes(path1)))); // pass ops.add(ZKUtilOp.deleteNodeFailSilent(path2)); // pass ops.add(ZKUtilOp.deleteNodeFailSilent(path3)); // fail -- node doesn't exist ops.add(ZKUtilOp.createAndFailSilent(path4, Bytes.add(Bytes.toBytes(path4), Bytes.toBytes(path4)))); // pass ZKUtil.multiOrSequential(zkw, ops, true); assertTrue(Bytes.equals(ZKUtil.getData(zkw, path1), Bytes.add(Bytes.toBytes(path1), Bytes.toBytes(path1)))); assertTrue(ZKUtil.checkExists(zkw, path2) == -1); assertTrue(ZKUtil.checkExists(zkw, path3) == -1); assertFalse(ZKUtil.checkExists(zkw, path4) == -1); }
@Test public void testSimpleMulti() throws Exception { // null multi ZKUtil.multiOrSequential(zkw, null, false); // empty multi ZKUtil.multiOrSequential(zkw, new LinkedList<>(), false); // single create String path = ZNodePaths.joinZNode(zkw.getZNodePaths().baseZNode, "testSimpleMulti"); LinkedList<ZKUtilOp> singleCreate = new LinkedList<>(); singleCreate.add(ZKUtilOp.createAndFailSilent(path, new byte[0])); ZKUtil.multiOrSequential(zkw, singleCreate, false); assertTrue(ZKUtil.checkExists(zkw, path) != -1); // single setdata LinkedList<ZKUtilOp> singleSetData = new LinkedList<>(); byte [] data = Bytes.toBytes("foobar"); singleSetData.add(ZKUtilOp.setData(path, data)); ZKUtil.multiOrSequential(zkw, singleSetData, false); assertTrue(Bytes.equals(ZKUtil.getData(zkw, path), data)); // single delete LinkedList<ZKUtilOp> singleDelete = new LinkedList<>(); singleDelete.add(ZKUtilOp.deleteNodeFailSilent(path)); ZKUtil.multiOrSequential(zkw, singleDelete, false); assertTrue(ZKUtil.checkExists(zkw, path) == -1); }
/** * Sets the data of the existing znode to be the specified data. The node * must exist but no checks are done on the existing data or version. * * <p>If the node does not exist, a {@link NoNodeException} will be thrown. * * <p>No watches are set but setting data will trigger other watchers of this * node. * * <p>If there is another problem, a KeeperException will be thrown. * * @param zkw zk reference * @param znode path of node * @param data data to set for node * @throws KeeperException if unexpected zookeeper exception */ public static void setData(ZKWatcher zkw, String znode, byte [] data) throws KeeperException, KeeperException.NoNodeException { setData(zkw, (SetData)ZKUtilOp.setData(znode, data)); }
@Override public void transitPeerSyncReplicationState(String peerId) throws ReplicationException { String newStateNode = getNewSyncReplicationStateNode(peerId); try { byte[] data = ZKUtil.getData(zookeeper, newStateNode); ZKUtil.multiOrSequential(zookeeper, Arrays.asList(ZKUtilOp.setData(newStateNode, NONE_STATE_ZNODE_BYTES), ZKUtilOp.setData(getSyncReplicationStateNode(peerId), data)), false); } catch (KeeperException | InterruptedException e) { throw new ReplicationException( "Error transiting sync replication state for peer with id=" + peerId, e); } }
@Test public void testSetDataWithVersion() throws Exception { ZKUtil.createWithParents(ZKW, "/s1/s2/s3"); int v0 = getZNodeDataVersion("/s1/s2/s3"); assertEquals(0, v0); ZKUtil.setData(ZKW, "/s1/s2/s3", Bytes.toBytes(12L)); int v1 = getZNodeDataVersion("/s1/s2/s3"); assertEquals(1, v1); ZKUtil.multiOrSequential(ZKW, ImmutableList.of(ZKUtilOp.setData("/s1/s2/s3", Bytes.toBytes(13L), v1)), false); int v2 = getZNodeDataVersion("/s1/s2/s3"); assertEquals(2, v2); }