@Test public void testSyncRemove() { 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); boolean success = accessor.remove(path, 0); Assert.assertFalse(success); success = accessor.create(path, record, AccessOption.PERSISTENT); Assert.assertTrue(success); ZNRecord getRecord = _gZkClient.readData(path); Assert.assertNotNull(getRecord); Assert.assertEquals(getRecord.getId(), "msg_0"); success = accessor.remove(path, 0); Assert.assertTrue(success); Assert.assertFalse(_gZkClient.exists(path)); System.out.println("END " + testName + " at " + new Date(System.currentTimeMillis())); }
@Test public void testSyncDoSet() { 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/%s", testName, "msg_0", "submsg_0"); ZNRecord record = new ZNRecord("submsg_0"); ZkBaseDataAccessor<ZNRecord> accessor = new ZkBaseDataAccessor<ZNRecord>(_gZkClient); AccessResult result = accessor.doSet(path, record, -1, AccessOption.PERSISTENT); Assert.assertEquals(result._retCode, RetCode.OK); Assert.assertEquals(result._pathCreated.size(), 3); Assert.assertTrue(result._pathCreated.contains(String.format("/%s", testName))); Assert.assertTrue(result._pathCreated.contains(String.format("/%s/%s", testName, "msg_0"))); Assert.assertTrue(result._pathCreated.contains(path)); Assert.assertTrue(_gZkClient.exists(String.format("/%s", testName))); Assert.assertTrue(_gZkClient.exists(String.format("/%s/%s", testName, "msg_0"))); ZNRecord getRecord = _gZkClient.readData(path); Assert.assertNotNull(getRecord); Assert.assertEquals(getRecord.getId(), "submsg_0"); System.out.println("END " + testName + " at " + new Date(System.currentTimeMillis())); }
@Test public void testSyncSetWithVersion() { 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"); BaseDataAccessor<ZNRecord> accessor = new ZkBaseDataAccessor<ZNRecord>(_gZkClient); // set persistent boolean success = accessor.set(path, record, 0, AccessOption.PERSISTENT); Assert.assertFalse(success, "Should fail since version not match"); try { _gZkClient.readData(path, false); Assert.fail("Should get no node exception"); } catch (Exception e) { // OK } success = accessor.set(path, record, -1, AccessOption.PERSISTENT); Assert.assertTrue(success); ZNRecord getRecord = _gZkClient.readData(path); Assert.assertNotNull(getRecord); Assert.assertEquals(getRecord.getId(), "msg_0"); // set ephemeral path = String.format("/%s/%s", testName, "msg_1"); record = new ZNRecord("msg_1"); success = accessor.set(path, record, 0, AccessOption.EPHEMERAL); Assert.assertFalse(success); try { _gZkClient.readData(path, false); Assert.fail("Should get no node exception"); } catch (Exception e) { // OK } success = accessor.set(path, record, -1, AccessOption.EPHEMERAL); Assert.assertTrue(success); getRecord = _gZkClient.readData(path); Assert.assertNotNull(getRecord); Assert.assertEquals(getRecord.getId(), "msg_1"); record.setSimpleField("key0", "value0"); success = accessor.set(path, record, 0, AccessOption.PERSISTENT); Assert.assertTrue(success, "Should pass. AccessOption.PERSISTENT is ignored"); getRecord = _gZkClient.readData(path); Assert.assertNotNull(getRecord); Assert.assertEquals(getRecord.getSimpleFields().size(), 1); Assert.assertNotNull(getRecord.getSimpleField("key0")); Assert.assertEquals(getRecord.getSimpleField("key0"), "value0"); System.out.println("END " + testName + " at " + new Date(System.currentTimeMillis())); }
private void prepare( String controllerVersion, String participantVersion, String minSupportedParticipantVersion) { List<String> instances = Arrays.asList("localhost_0", "localhost_1", "localhost_2", "localhost_3", "localhost_4"); int partitions = 10; int replicas = 1; // set ideal state String resourceName = "testResource"; ZNRecord record = DefaultTwoStateStrategy.calculateIdealState( instances, partitions, replicas, resourceName, "MASTER", "SLAVE"); IdealState idealState = new IdealState(record); idealState.setStateModelDefId(StateModelDefinitionId.from("MasterSlave")); PropertyKeyBuilder keyBuilder = accessor.keyBuilder(); accessor.setProperty(keyBuilder.idealStates(resourceName), idealState); // set live instances record = new ZNRecord("localhost_0"); if (participantVersion != null) { record.setSimpleField(LiveInstanceProperty.HELIX_VERSION.toString(), participantVersion); } LiveInstance liveInstance = new LiveInstance(record); liveInstance.setSessionId("session_0"); accessor.setProperty(keyBuilder.liveInstance("localhost_0"), liveInstance); InstanceConfig config = new InstanceConfig(liveInstance.getInstanceName()); accessor.setProperty(keyBuilder.instanceConfig(config.getInstanceName()), config); if (controllerVersion != null) { ((Mocks.MockManager) manager).setVersion(controllerVersion); } if (minSupportedParticipantVersion != null) { manager .getProperties() .getProperties() .put("minimum_supported_version.participant", minSupportedParticipantVersion); } event.addAttribute("helixmanager", manager); runStage(event, new ReadClusterDataStage()); }
/* * The parameter is a map that maps the nodeName to a list of ZNRecords. */ public List<ZNRecord> computeExternalView( Map<String, List<ZNRecord>> currentStates, List<ZNRecord> idealStates) { List<ZNRecord> resultList = new ArrayList<ZNRecord>(); Map<String, ZNRecord> resultRoutingTable = new HashMap<String, ZNRecord>(); // maps from resourceName to another map : partition -> map <nodename, // master/slave>; // Fill the routing table with "empty" default state according to ideals // states // in the cluster if (idealStates != null) { for (ZNRecord idealState : idealStates) { ZNRecord defaultExternalView = new ZNRecord(idealState.getId()); resultRoutingTable.put(idealState.getId(), defaultExternalView); } } else { assert (!currentStates.isEmpty()); return resultList; } for (String nodeName : currentStates.keySet()) { List<ZNRecord> znStates = currentStates.get(nodeName); for (ZNRecord nodeStateRecord : znStates) { Map<String, Map<String, String>> resourceStates = nodeStateRecord.getMapFields(); for (String stateUnitKey : resourceStates.keySet()) { Map<String, String> partitionStates = resourceStates.get(stateUnitKey); String resourceName = partitionStates.get(Message.Attributes.RESOURCE_NAME.toString()); ZNRecord partitionStatus = resultRoutingTable.get(resourceName); if (partitionStatus == null) { partitionStatus = new ZNRecord(resourceName); resultRoutingTable.put(resourceName, partitionStatus); } String currentStateKey = CurrentStateProperty.CURRENT_STATE.toString(); if (!partitionStatus.getMapFields().containsKey(stateUnitKey)) { partitionStatus.setMapField(stateUnitKey, new TreeMap<String, String>()); } partitionStatus .getMapField(stateUnitKey) .put(nodeName, partitionStates.get(currentStateKey)); } } } for (ZNRecord record : resultRoutingTable.values()) { resultList.add(record); } return resultList; }
/* * Given a list of external view ZNRecord nodes(one for each cluster), * calculate the routing map. * The format of the routing map is like this: * Map<String, Map<String, Set<String>>> maps from a partitionName to its * states Map<String, List<String>> The second Map maps from a state * ("MASTER", "SLAVE"...) to a list of nodeNames * So that the we can query the map for the list of nodes by providing the * partition name and the expected state. */ public Map<String, Map<String, Set<String>>> getRouterMapFromExternalView( List<ZNRecord> externalViewList) { Map<String, Map<String, Set<String>>> result = new TreeMap<String, Map<String, Set<String>>>(); for (ZNRecord nodeView : externalViewList) { Map<String, Map<String, String>> partitionNodeStateMap = nodeView.getMapFields(); for (String partitionId : partitionNodeStateMap.keySet()) { if (!result.containsKey(partitionId)) { result.put(partitionId, new TreeMap<String, Set<String>>()); } Map<String, String> nodeStateMap = partitionNodeStateMap.get(partitionId); for (String nodeName : nodeStateMap.keySet()) { String state = nodeStateMap.get(nodeName); if (!result.get(partitionId).containsKey(state)) { result.get(partitionId).put(state, new TreeSet<String>()); } result.get(partitionId).get(state).add(nodeName); } } } return result; }
@Test public void testSyncUpdate() { 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); boolean success = accessor.update(path, new ZNRecordUpdater(record), AccessOption.PERSISTENT); Assert.assertTrue(success); ZNRecord getRecord = _gZkClient.readData(path); Assert.assertNotNull(getRecord); Assert.assertEquals(getRecord.getId(), "msg_0"); record.setSimpleField("key0", "value0"); success = accessor.update(path, new ZNRecordUpdater(record), AccessOption.PERSISTENT); Assert.assertTrue(success); getRecord = _gZkClient.readData(path); Assert.assertNotNull(getRecord); Assert.assertEquals(getRecord.getSimpleFields().size(), 1); Assert.assertNotNull(getRecord.getSimpleField("key0")); Assert.assertEquals(getRecord.getSimpleField("key0"), "value0"); // test throw exception from updater success = accessor.update( path, new DataUpdater<ZNRecord>() { @Override public ZNRecord update(ZNRecord currentData) { throw new RuntimeException("IGNORABLE: test throw exception from updater"); } }, AccessOption.PERSISTENT); Assert.assertFalse(success); getRecord = _gZkClient.readData(path); Assert.assertNotNull(getRecord); Assert.assertEquals(getRecord.getSimpleFields().size(), 1); System.out.println("END " + testName + " at " + new Date(System.currentTimeMillis())); }
/** * Do a group update for data associated with a given key * * @param accessor accessor with the ability to pull from the current data * @param options see {@link AccessOption} * @param key the data identifier * @param record the data to be merged in * @return true if successful, false otherwise */ public boolean commit( BaseDataAccessor<ZNRecord> accessor, int options, String key, ZNRecord record) { Queue queue = getQueue(key); Entry entry = new Entry(key, record); queue._pending.add(entry); while (!entry._sent.get()) { if (queue._running.compareAndSet(null, Thread.currentThread())) { ArrayList<Entry> processed = new ArrayList<Entry>(); try { if (queue._pending.peek() == null) return true; // remove from queue Entry first = queue._pending.poll(); processed.add(first); String mergedKey = first._key; // ZNRecord merged = _cache.get(mergedKey); ZNRecord merged = null; try { // accessor will fallback to zk if not found in cache merged = accessor.get(mergedKey, null, options); } catch (ZkNoNodeException e) { // OK. } /** * If the local cache does not contain a value, need to check if there is a value in ZK; * use it as initial value if exists */ if (merged == null) { // ZNRecord valueOnZk = null; // try // { // valueOnZk = accessor.get(mergedKey, null, 0); // } // catch(Exception e) // { // LOG.info(e); // } // if(valueOnZk != null) // { // merged = valueOnZk; // merged.merge(first._record); // } // else // Zk path has null data. use the first record as initial record. { merged = new ZNRecord(first._record); } } else { merged.merge(first._record); } Iterator<Entry> it = queue._pending.iterator(); while (it.hasNext()) { Entry ent = it.next(); if (!ent._key.equals(mergedKey)) continue; processed.add(ent); merged.merge(ent._record); // System.out.println("After merging:" + merged); it.remove(); } // System.out.println("size:"+ processed.size()); accessor.set(mergedKey, merged, options); // accessor.set(mergedKey, merged, BaseDataAccessor.Option.PERSISTENT); // _cache.put(mergedKey, merged); } finally { queue._running.set(null); for (Entry e : processed) { synchronized (e) { e._sent.set(true); e.notify(); } } } } else { synchronized (entry) { try { entry.wait(10); } catch (InterruptedException e) { e.printStackTrace(); return false; } } } } return true; }
@Test public void testAsyncZkBaseDataAccessor() { System.out.println( "START TestZkBaseDataAccessor.async at " + new Date(System.currentTimeMillis())); String root = "TestZkBaseDataAccessor_asyn"; ZkClient zkClient = new ZkClient(ZK_ADDR); zkClient.setZkSerializer(new ZNRecordSerializer()); zkClient.deleteRecursive("/" + root); ZkBaseDataAccessor<ZNRecord> accessor = new ZkBaseDataAccessor<ZNRecord>(zkClient); // test async createChildren String parentPath = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1"); List<ZNRecord> records = new ArrayList<ZNRecord>(); List<String> paths = new ArrayList<String>(); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; paths.add(PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId)); records.add(new ZNRecord(msgId)); } boolean[] success = accessor.createChildren(paths, records, AccessOption.PERSISTENT); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; Assert.assertTrue(success[i], "Should succeed in create " + msgId); } // test get what we created for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; String path = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId); ZNRecord record = zkClient.readData(path); Assert.assertEquals(record.getId(), msgId, "Should get what we created"); } // test async setChildren parentPath = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1"); records = new ArrayList<ZNRecord>(); paths = new ArrayList<String>(); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; paths.add(PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId)); ZNRecord newRecord = new ZNRecord(msgId); newRecord.setSimpleField("key1", "value1"); records.add(newRecord); } success = accessor.setChildren(paths, records, AccessOption.PERSISTENT); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; Assert.assertTrue(success[i], "Should succeed in set " + msgId); } // test get what we set for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; String path = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId); ZNRecord record = zkClient.readData(path); Assert.assertEquals(record.getSimpleFields().size(), 1, "Should have 1 simple field set"); Assert.assertEquals(record.getSimpleField("key1"), "value1", "Should have value1 set"); } // test async updateChildren parentPath = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1"); // records = new ArrayList<ZNRecord>(); List<DataUpdater<ZNRecord>> znrecordUpdaters = new ArrayList<DataUpdater<ZNRecord>>(); paths = new ArrayList<String>(); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; paths.add(PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId)); ZNRecord newRecord = new ZNRecord(msgId); newRecord.setSimpleField("key2", "value2"); // records.add(newRecord); znrecordUpdaters.add(new ZNRecordUpdater(newRecord)); } success = accessor.updateChildren(paths, znrecordUpdaters, AccessOption.PERSISTENT); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; Assert.assertTrue(success[i], "Should succeed in update " + msgId); } // test get what we updated for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; String path = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId); ZNRecord record = zkClient.readData(path); Assert.assertEquals(record.getSimpleFields().size(), 2, "Should have 2 simple fields set"); Assert.assertEquals(record.getSimpleField("key2"), "value2", "Should have value2 set"); } // test async getChildren parentPath = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1"); records = accessor.getChildren(parentPath, null, 0); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; ZNRecord record = records.get(i); Assert.assertEquals(record.getId(), msgId, "Should get what we updated"); Assert.assertEquals(record.getSimpleFields().size(), 2, "Should have 2 simple fields set"); Assert.assertEquals(record.getSimpleField("key2"), "value2", "Should have value2 set"); } // test async exists parentPath = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1"); paths = new ArrayList<String>(); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; paths.add(PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId)); } boolean[] exists = accessor.exists(paths, 0); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; Assert.assertTrue(exists[i], "Should exist " + msgId); } // test async getStats parentPath = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1"); paths = new ArrayList<String>(); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; paths.add(PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId)); } Stat[] stats = accessor.getStats(paths, 0); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; Assert.assertNotNull(stats[i], "Stat should exist for " + msgId); Assert.assertEquals( stats[i].getVersion(), 2, "DataVersion should be 2, since we set 1 and update 1 for " + msgId); } // test async remove parentPath = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1"); paths = new ArrayList<String>(); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; paths.add(PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId)); } success = accessor.remove(paths, 0); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; Assert.assertTrue(success[i], "Should succeed in remove " + msgId); } // test get what we removed for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; String path = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId); boolean pathExists = zkClient.exists(path); Assert.assertFalse(pathExists, "Should be removed " + msgId); } zkClient.close(); System.out.println( "END TestZkBaseDataAccessor.async at " + new Date(System.currentTimeMillis())); }
@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())); }
@Override public ResourceAssignment computeResourceMapping( RebalancerConfiguration rebalancerConfig, ResourceAssignment prevAssignment, Cluster cluster, ResourceCurrentState currentState) { FullAutoRebalancerConfig config = BasicRebalancerConfig.convert(rebalancerConfig, FullAutoRebalancerConfig.class); StateModelDefinition stateModelDef = cluster.getStateModelMap().get(config.getStateModelDefId()); // Compute a preference list based on the current ideal state List<PartitionId> partitions = new ArrayList<PartitionId>(config.getPartitionSet()); Map<ParticipantId, Participant> liveParticipants = cluster.getLiveParticipantMap(); Map<ParticipantId, Participant> allParticipants = cluster.getParticipantMap(); int replicas = -1; if (partitions.size() > 0 && config.getAnyLiveParticipant(partitions.get(0))) { replicas = liveParticipants.size(); } else { replicas = config.getReplicaCount(); } // count how many replicas should be in each state Map<State, String> upperBounds = ConstraintBasedAssignment.stateConstraints( stateModelDef, config.getResourceId(), cluster.getConfig()); LinkedHashMap<State, Integer> stateCountMap = ConstraintBasedAssignment.stateCount( upperBounds, stateModelDef, liveParticipants.size(), replicas); // get the participant lists List<ParticipantId> liveParticipantList = new ArrayList<ParticipantId>(liveParticipants.keySet()); List<ParticipantId> allParticipantList = new ArrayList<ParticipantId>(cluster.getParticipantMap().keySet()); // compute the current mapping from the current state Map<PartitionId, Map<ParticipantId, State>> currentMapping = currentMapping(config, currentState, stateCountMap); // If there are nodes tagged with resource, use only those nodes // If there are nodes tagged with resource name, use only those nodes Set<ParticipantId> taggedNodes = new HashSet<ParticipantId>(); Set<ParticipantId> taggedLiveNodes = new HashSet<ParticipantId>(); if (config.getParticipantGroupTag() != null) { for (ParticipantId participantId : allParticipantList) { if (cluster .getParticipantMap() .get(participantId) .hasTag(config.getParticipantGroupTag())) { taggedNodes.add(participantId); if (liveParticipants.containsKey(participantId)) { taggedLiveNodes.add(participantId); } } } if (!taggedLiveNodes.isEmpty()) { // live nodes exist that have this tag if (LOG.isDebugEnabled()) { LOG.debug( "found the following participants with tag " + config.getParticipantGroupTag() + " for " + config.getResourceId() + ": " + taggedLiveNodes); } } else if (taggedNodes.isEmpty()) { // no live nodes and no configured nodes have this tag LOG.warn( "Resource " + config.getResourceId() + " has tag " + config.getParticipantGroupTag() + " but no configured participants have this tag"); } else { // configured nodes have this tag, but no live nodes have this tag LOG.warn( "Resource " + config.getResourceId() + " has tag " + config.getParticipantGroupTag() + " but no live participants have this tag"); } allParticipantList = new ArrayList<ParticipantId>(taggedNodes); liveParticipantList = new ArrayList<ParticipantId>(taggedLiveNodes); } // determine which nodes the replicas should live on int maxPartition = config.getMaxPartitionsPerParticipant(); if (LOG.isDebugEnabled()) { LOG.debug("currentMapping: " + currentMapping); LOG.debug("stateCountMap: " + stateCountMap); LOG.debug("liveNodes: " + liveParticipantList); LOG.debug("allNodes: " + allParticipantList); LOG.debug("maxPartition: " + maxPartition); } ReplicaPlacementScheme placementScheme = new DefaultPlacementScheme(); _algorithm = new AutoRebalanceStrategy( config.getResourceId(), partitions, stateCountMap, maxPartition, placementScheme); ZNRecord newMapping = _algorithm.typedComputePartitionAssignment( liveParticipantList, currentMapping, allParticipantList); if (LOG.isInfoEnabled()) { LOG.info("newMapping: " + newMapping); } // compute a full partition mapping for the resource if (LOG.isDebugEnabled()) { LOG.debug("Processing resource:" + config.getResourceId()); } ResourceAssignment partitionMapping = new ResourceAssignment(config.getResourceId()); for (PartitionId partition : partitions) { Set<ParticipantId> disabledParticipantsForPartition = ConstraintBasedAssignment.getDisabledParticipants(allParticipants, partition); List<String> rawPreferenceList = newMapping.getListField(partition.toString()); if (rawPreferenceList == null) { rawPreferenceList = Collections.emptyList(); } List<ParticipantId> preferenceList = Lists.transform( rawPreferenceList, new Function<String, ParticipantId>() { @Override public ParticipantId apply(String participantName) { return ParticipantId.from(participantName); } }); preferenceList = ConstraintBasedAssignment.getPreferenceList(cluster, partition, preferenceList); Map<ParticipantId, State> bestStateForPartition = ConstraintBasedAssignment.computeAutoBestStateForPartition( upperBounds, liveParticipants.keySet(), stateModelDef, preferenceList, currentState.getCurrentStateMap(config.getResourceId(), partition), disabledParticipantsForPartition); partitionMapping.addReplicaMap(partition, bestStateForPartition); } return partitionMapping; }