This is an automated email from the ASF dual-hosted git repository. jackie pushed a commit to branch resource_allocation in repository https://gitbox.apache.org/repos/asf/incubator-pinot.git
commit 0cec0992433d1031a033ab15a1800aef196fd3d2 Author: Xiaotian (Jackie) Jiang <[email protected]> AuthorDate: Fri Nov 30 20:32:34 2018 -0800 Initial commit on the interfaces --- .../pinot/common/config/AssignmentConfig.java | 19 ++++ .../core/assignment/instance/InstanceRole.java | 20 ++++ .../instance/InstanceSelectionResult.java | 45 ++++++++ .../instance/InstanceSelectionResultUtils.java | 38 +++++++ .../instance/InstanceSelectionStrategy.java | 26 +++++ .../core/assignment/instance/InstanceTags.java | 116 ++++++++++++++++++++ .../assignment/instance/InstanceTagsUtils.java | 42 ++++++++ .../instance/constraint/InstanceConstraint.java | 30 ++++++ .../constraint/NumInstancesConstraint.java | 30 ++++++ .../constraint/ReplicaGroupInstanceConstraint.java | 30 ++++++ .../TagExactMatchInstanceConstraint.java | 48 +++++++++ .../segment/SegmentAssignmentStrategy.java | 34 ++++++ .../core/assignment/instance/InstanceTagsTest.java | 117 +++++++++++++++++++++ 13 files changed, 595 insertions(+) diff --git a/pinot-common/src/main/java/com/linkedin/pinot/common/config/AssignmentConfig.java b/pinot-common/src/main/java/com/linkedin/pinot/common/config/AssignmentConfig.java new file mode 100644 index 0000000..51093dd --- /dev/null +++ b/pinot-common/src/main/java/com/linkedin/pinot/common/config/AssignmentConfig.java @@ -0,0 +1,19 @@ +/** + * Copyright (C) 2014-2018 LinkedIn Corp. ([email protected]) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.linkedin.pinot.common.config; + +public class AssignmentConfig { +} diff --git a/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/InstanceRole.java b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/InstanceRole.java new file mode 100644 index 0000000..8221a3c --- /dev/null +++ b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/InstanceRole.java @@ -0,0 +1,20 @@ +/** + * Copyright (C) 2014-2018 LinkedIn Corp. ([email protected]) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.linkedin.pinot.controller.helix.core.assignment.instance; + +public enum InstanceRole { + CONTROLLER, BROKER, SERVER, OFFLINE, REALTIME, MINION +} diff --git a/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/InstanceSelectionResult.java b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/InstanceSelectionResult.java new file mode 100644 index 0000000..5e12f6c --- /dev/null +++ b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/InstanceSelectionResult.java @@ -0,0 +1,45 @@ +/** + * Copyright (C) 2014-2018 LinkedIn Corp. ([email protected]) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.linkedin.pinot.controller.helix.core.assignment.instance; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +public class InstanceSelectionResult { + private final Map<Integer, List<String>> _replicaIdToInstancesMap; + + public InstanceSelectionResult() { + _replicaIdToInstancesMap = new HashMap<>(); + } + + public InstanceSelectionResult(Map<Integer, List<String>> replicaIdToInstancesMap) { + _replicaIdToInstancesMap = replicaIdToInstancesMap; + } + + public int getNumReplicas() { + return _replicaIdToInstancesMap.size(); + } + + public List<String> getInstances(int replicaId) { + return _replicaIdToInstancesMap.get(replicaId); + } + + public void setInstances(int replicaId, List<String> instances) { + _replicaIdToInstancesMap.put(replicaId, instances); + } +} diff --git a/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/InstanceSelectionResultUtils.java b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/InstanceSelectionResultUtils.java new file mode 100644 index 0000000..1e22e58 --- /dev/null +++ b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/InstanceSelectionResultUtils.java @@ -0,0 +1,38 @@ +/** + * Copyright (C) 2014-2018 LinkedIn Corp. ([email protected]) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.linkedin.pinot.controller.helix.core.assignment.instance; + +import java.util.Map; +import org.apache.helix.ZNRecord; +import org.apache.helix.store.zk.ZkHelixPropertyStore; + + +public class InstanceSelectionResultUtils { + private InstanceSelectionResultUtils() { + } + + public static Map<InstanceRole, InstanceSelectionResult> readFromZK(ZkHelixPropertyStore<ZNRecord> propertyStore, + String resource) { + //TODO: implement it + throw new UnsupportedOperationException(); + } + + public static boolean writeToZK(ZkHelixPropertyStore<ZNRecord> propertyStore, String resource, + Map<InstanceRole, InstanceSelectionResult> instanceSelectionResults) { + //TODO: implement it + throw new UnsupportedOperationException(); + } +} diff --git a/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/InstanceSelectionStrategy.java b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/InstanceSelectionStrategy.java new file mode 100644 index 0000000..7ecd234 --- /dev/null +++ b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/InstanceSelectionStrategy.java @@ -0,0 +1,26 @@ +/** + * Copyright (C) 2014-2018 LinkedIn Corp. ([email protected]) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.linkedin.pinot.controller.helix.core.assignment.instance; + +import com.linkedin.pinot.common.config.AssignmentConfig; +import javax.annotation.Nullable; + + +public interface InstanceSelectionStrategy { + + InstanceSelectionResult selectInstances(AssignmentConfig assignmentConfig, + @Nullable InstanceSelectionResult existingSelectionResult); +} diff --git a/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/InstanceTags.java b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/InstanceTags.java new file mode 100644 index 0000000..a242e85 --- /dev/null +++ b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/InstanceTags.java @@ -0,0 +1,116 @@ +/** + * Copyright (C) 2014-2018 LinkedIn Corp. ([email protected]) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.linkedin.pinot.controller.helix.core.assignment.instance; + +import com.google.common.base.Preconditions; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.Nullable; +import org.apache.commons.lang3.EnumUtils; +import org.apache.commons.lang3.StringUtils; + + +public class InstanceTags { + private static final char TAG_DELIMITER = ';'; + private static final char KEY_VALUE_DELIMITER = ':'; + private static final char LEGACY_DELIMITER = '_'; + private static final String UNTAGGED = "untagged"; + + public static final String ROLE_KEY = "role"; + public static final String POOL_NAME_KEY = "poolName"; + public static final String GROUP_ID_KEY = "groupId"; + + private final String _instanceName; + private final Map<String, String> _tags; + + public InstanceTags(String instanceName, Map<String, String> tags) { + _instanceName = instanceName; + _tags = tags; + } + + public static InstanceTags fromHelixTag(String instanceName, String helixTag) { + Map<String, String> tags = new HashMap<>(); + + // For backward-compatible + if (helixTag.indexOf(KEY_VALUE_DELIMITER) == -1) { + int delimiterIndex = helixTag.lastIndexOf(LEGACY_DELIMITER); + Preconditions.checkArgument(delimiterIndex != -1, "Invalid Helix tag: " + helixTag); + + String part1 = helixTag.substring(0, delimiterIndex); + String part2 = helixTag.substring(delimiterIndex + 1); + if (part2.equals(UNTAGGED)) { + // Untagged instances, e.g. broker_untagged, server_untagged, minion_untagged + InstanceRole role = InstanceRole.valueOf(part1.toUpperCase()); + tags.put(ROLE_KEY, role.toString()); + tags.put(POOL_NAME_KEY, UNTAGGED); + tags.put(GROUP_ID_KEY, Integer.toString(0)); + } else { + // Tagged instances, e.g. poolName_OFFLINE, poolName_REALTIME, poolName_BROKER + String poolName = helixTag.substring(0, delimiterIndex); + String role = helixTag.substring(delimiterIndex + 1); + Preconditions.checkArgument(EnumUtils.isValidEnum(InstanceRole.class, role), "Invalid role: " + role); + + tags.put(ROLE_KEY, role); + tags.put(POOL_NAME_KEY, poolName); + tags.put(GROUP_ID_KEY, Integer.toString(0)); + } + } else { + // E.g. role:BROKER;poolName:brokerPool;groupId:0 + String[] pairs = StringUtils.split(helixTag, TAG_DELIMITER); + for (String pair : pairs) { + String[] keyAndValue = StringUtils.split(pair, KEY_VALUE_DELIMITER); + Preconditions.checkArgument(keyAndValue.length == 2, "Invalid ket-value pair: " + pair); + tags.put(keyAndValue[0], keyAndValue[1]); + } + } + + return new InstanceTags(instanceName, tags); + } + + public static String toHelixTag(InstanceTags instanceTags) { + StringBuilder stringBuilder = new StringBuilder(); + for (Map.Entry<String, String> entry : instanceTags._tags.entrySet()) { + stringBuilder.append(entry.getKey()).append(KEY_VALUE_DELIMITER).append(entry.getValue()).append(TAG_DELIMITER); + } + return stringBuilder.substring(0, stringBuilder.length() - 1); + } + + public String getInstanceName() { + return _instanceName; + } + + @Nullable + public String getTag(String key) { + return _tags.get(key); + } + + @Override + public int hashCode() { + return 37 * _instanceName.hashCode() + _tags.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof InstanceTags) { + InstanceTags that = (InstanceTags) obj; + return _instanceName.equals(that._instanceName) && _tags.equals(that._tags); + } + return false; + } +} diff --git a/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/InstanceTagsUtils.java b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/InstanceTagsUtils.java new file mode 100644 index 0000000..df7b213 --- /dev/null +++ b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/InstanceTagsUtils.java @@ -0,0 +1,42 @@ +/** + * Copyright (C) 2014-2018 LinkedIn Corp. ([email protected]) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.linkedin.pinot.controller.helix.core.assignment.instance; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.apache.helix.model.InstanceConfig; + + +public class InstanceTagsUtils { + private InstanceTagsUtils() { + } + + public static Set<InstanceTags> extractAllInstanceTags(List<InstanceConfig> instanceConfigs) { + Set<InstanceTags> instanceTagsSet = new HashSet<>(); + for (InstanceConfig instanceConfig : instanceConfigs) { + // Skip disabled instances + if (!instanceConfig.getInstanceEnabled()) { + continue; + } + String instanceName = instanceConfig.getInstanceName(); + for (String tag : instanceConfig.getTags()) { + instanceTagsSet.add(InstanceTags.fromHelixTag(instanceName, tag)); + } + } + return instanceTagsSet; + } +} diff --git a/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/constraint/InstanceConstraint.java b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/constraint/InstanceConstraint.java new file mode 100644 index 0000000..c391bbd --- /dev/null +++ b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/constraint/InstanceConstraint.java @@ -0,0 +1,30 @@ +/** + * Copyright (C) 2014-2018 LinkedIn Corp. ([email protected]) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.linkedin.pinot.controller.helix.core.assignment.instance.constraint; + +import com.linkedin.pinot.controller.helix.core.assignment.instance.InstanceTags; +import java.util.Map; +import java.util.Set; + + +public interface InstanceConstraint { + int UNASSIGNED_REPLICA_ID = -1; + + /** + * Applies the instance constraint, and returns a map from replica Id to satisfied instances. + */ + Map<Integer, Set<InstanceTags>> apply(Map<Integer, Set<InstanceTags>> replicaIdToInstanceTagsMap); +} diff --git a/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/constraint/NumInstancesConstraint.java b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/constraint/NumInstancesConstraint.java new file mode 100644 index 0000000..713d8c0 --- /dev/null +++ b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/constraint/NumInstancesConstraint.java @@ -0,0 +1,30 @@ +/** + * Copyright (C) 2014-2018 LinkedIn Corp. ([email protected]) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.linkedin.pinot.controller.helix.core.assignment.instance.constraint; + +import com.linkedin.pinot.controller.helix.core.assignment.instance.InstanceTags; +import java.util.Map; +import java.util.Set; + + +public class NumInstancesConstraint implements InstanceConstraint { + + @Override + public Map<Integer, Set<InstanceTags>> apply(Map<Integer, Set<InstanceTags>> replicaIdToInstanceTagsMap) { + //TODO: implement it + throw new UnsupportedOperationException(); + } +} diff --git a/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/constraint/ReplicaGroupInstanceConstraint.java b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/constraint/ReplicaGroupInstanceConstraint.java new file mode 100644 index 0000000..1efdf21 --- /dev/null +++ b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/constraint/ReplicaGroupInstanceConstraint.java @@ -0,0 +1,30 @@ +/** + * Copyright (C) 2014-2018 LinkedIn Corp. ([email protected]) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.linkedin.pinot.controller.helix.core.assignment.instance.constraint; + +import com.linkedin.pinot.controller.helix.core.assignment.instance.InstanceTags; +import java.util.Map; +import java.util.Set; + + +public class ReplicaGroupInstanceConstraint implements InstanceConstraint { + + @Override + public Map<Integer, Set<InstanceTags>> apply(Map<Integer, Set<InstanceTags>> replicaIdToInstanceTagsMap) { + //TODO: implement it + throw new UnsupportedOperationException(); + } +} diff --git a/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/constraint/TagExactMatchInstanceConstraint.java b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/constraint/TagExactMatchInstanceConstraint.java new file mode 100644 index 0000000..c6e79b8 --- /dev/null +++ b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/instance/constraint/TagExactMatchInstanceConstraint.java @@ -0,0 +1,48 @@ +/** + * Copyright (C) 2014-2018 LinkedIn Corp. ([email protected]) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.linkedin.pinot.controller.helix.core.assignment.instance.constraint; + +import com.linkedin.pinot.controller.helix.core.assignment.instance.InstanceTags; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + + +public class TagExactMatchInstanceConstraint implements InstanceConstraint { + private final Map<String, String> _exactMatchTags; + + public TagExactMatchInstanceConstraint(Map<String, String> exactMatchTags) { + _exactMatchTags = exactMatchTags; + } + + @Override + public Map<Integer, Set<InstanceTags>> apply(Map<Integer, Set<InstanceTags>> replicaIdToInstanceTagsMap) { + for (Set<InstanceTags> instanceTagsSet : replicaIdToInstanceTagsMap.values()) { + Iterator<InstanceTags> iterator = instanceTagsSet.iterator(); + while (iterator.hasNext()) { + InstanceTags instanceTags = iterator.next(); + for (Map.Entry<String, String> entry : _exactMatchTags.entrySet()) { + String tag = instanceTags.getTag(entry.getKey()); + if (!entry.getValue().equals(tag)) { + iterator.remove(); + break; + } + } + } + } + return replicaIdToInstanceTagsMap; + } +} diff --git a/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/segment/SegmentAssignmentStrategy.java b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/segment/SegmentAssignmentStrategy.java new file mode 100644 index 0000000..ab1de3c --- /dev/null +++ b/pinot-controller/src/main/java/com/linkedin/pinot/controller/helix/core/assignment/segment/SegmentAssignmentStrategy.java @@ -0,0 +1,34 @@ +/** + * Copyright (C) 2014-2018 LinkedIn Corp. ([email protected]) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.linkedin.pinot.controller.helix.core.assignment.segment; + +import com.linkedin.pinot.common.config.AssignmentConfig; +import com.linkedin.pinot.common.metadata.segment.SegmentZKMetadata; +import com.linkedin.pinot.controller.helix.core.assignment.instance.InstanceSelectionResult; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; + + +public interface SegmentAssignmentStrategy { + + Map<String, List<String>> assignNewSegment(AssignmentConfig assignmentConfig, SegmentZKMetadata segmentZKMetadata, + InstanceSelectionResult selectedInstances, @Nullable Map<String, List<String>> existingAssignmentResult); + + Map<String, List<String>> rebalanceSegments(AssignmentConfig assignmentConfig, + List<SegmentZKMetadata> segmentZKMetadataList, InstanceSelectionResult selectedInstances, + Map<String, List<String>> existingAssignmentResult); +} diff --git a/pinot-controller/src/test/java/com/linkedin/pinot/controller/helix/core/assignment/instance/InstanceTagsTest.java b/pinot-controller/src/test/java/com/linkedin/pinot/controller/helix/core/assignment/instance/InstanceTagsTest.java new file mode 100644 index 0000000..a1ad642 --- /dev/null +++ b/pinot-controller/src/test/java/com/linkedin/pinot/controller/helix/core/assignment/instance/InstanceTagsTest.java @@ -0,0 +1,117 @@ +/** + * Copyright (C) 2014-2018 LinkedIn Corp. ([email protected]) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.linkedin.pinot.controller.helix.core.assignment.instance; + +import org.testng.annotations.Test; + +import static org.testng.Assert.*; + + +public class InstanceTagsTest { + + @Test + public void testUntaggedInstance() { + InstanceTags instanceTags = InstanceTags.fromHelixTag("instance", "controller_untagged"); + assertEquals(instanceTags.getInstanceName(), "instance"); + assertEquals(instanceTags.getTag(InstanceTags.ROLE_KEY), InstanceRole.CONTROLLER.toString()); + assertEquals(instanceTags.getTag(InstanceTags.POOL_NAME_KEY), "untagged"); + assertEquals(instanceTags.getTag(InstanceTags.GROUP_ID_KEY), "0"); + + instanceTags = InstanceTags.fromHelixTag("instance", "broker_untagged"); + assertEquals(instanceTags.getInstanceName(), "instance"); + assertEquals(instanceTags.getTag(InstanceTags.ROLE_KEY), InstanceRole.BROKER.toString()); + assertEquals(instanceTags.getTag(InstanceTags.POOL_NAME_KEY), "untagged"); + assertEquals(instanceTags.getTag(InstanceTags.GROUP_ID_KEY), "0"); + + instanceTags = InstanceTags.fromHelixTag("instance", "server_untagged"); + assertEquals(instanceTags.getInstanceName(), "instance"); + assertEquals(instanceTags.getTag(InstanceTags.ROLE_KEY), InstanceRole.SERVER.toString()); + assertEquals(instanceTags.getTag(InstanceTags.POOL_NAME_KEY), "untagged"); + assertEquals(instanceTags.getTag(InstanceTags.GROUP_ID_KEY), "0"); + + instanceTags = InstanceTags.fromHelixTag("instance", "minion_untagged"); + assertEquals(instanceTags.getInstanceName(), "instance"); + assertEquals(instanceTags.getTag(InstanceTags.ROLE_KEY), InstanceRole.MINION.toString()); + assertEquals(instanceTags.getTag(InstanceTags.POOL_NAME_KEY), "untagged"); + assertEquals(instanceTags.getTag(InstanceTags.GROUP_ID_KEY), "0"); + } + + @Test + public void testLegacyHelixTag() { + InstanceTags instanceTags = InstanceTags.fromHelixTag("instance", "controllerPool_CONTROLLER"); + assertEquals(instanceTags.getInstanceName(), "instance"); + assertEquals(instanceTags.getTag(InstanceTags.ROLE_KEY), InstanceRole.CONTROLLER.toString()); + assertEquals(instanceTags.getTag(InstanceTags.POOL_NAME_KEY), "controllerPool"); + assertEquals(instanceTags.getTag(InstanceTags.GROUP_ID_KEY), "0"); + + instanceTags = InstanceTags.fromHelixTag("instance", "brokerPool_BROKER"); + assertEquals(instanceTags.getInstanceName(), "instance"); + assertEquals(instanceTags.getTag(InstanceTags.ROLE_KEY), InstanceRole.BROKER.toString()); + assertEquals(instanceTags.getTag(InstanceTags.POOL_NAME_KEY), "brokerPool"); + assertEquals(instanceTags.getTag(InstanceTags.GROUP_ID_KEY), "0"); + + instanceTags = InstanceTags.fromHelixTag("instance", "offlineServerPool_OFFLINE"); + assertEquals(instanceTags.getInstanceName(), "instance"); + assertEquals(instanceTags.getTag(InstanceTags.ROLE_KEY), InstanceRole.OFFLINE.toString()); + assertEquals(instanceTags.getTag(InstanceTags.POOL_NAME_KEY), "offlineServerPool"); + assertEquals(instanceTags.getTag(InstanceTags.GROUP_ID_KEY), "0"); + + instanceTags = InstanceTags.fromHelixTag("instance", "realtimeServerPool_REALTIME"); + assertEquals(instanceTags.getInstanceName(), "instance"); + assertEquals(instanceTags.getTag(InstanceTags.ROLE_KEY), InstanceRole.REALTIME.toString()); + assertEquals(instanceTags.getTag(InstanceTags.POOL_NAME_KEY), "realtimeServerPool"); + assertEquals(instanceTags.getTag(InstanceTags.GROUP_ID_KEY), "0"); + + instanceTags = InstanceTags.fromHelixTag("instance", "minionPool_MINION"); + assertEquals(instanceTags.getInstanceName(), "instance"); + assertEquals(instanceTags.getTag(InstanceTags.ROLE_KEY), InstanceRole.MINION.toString()); + assertEquals(instanceTags.getTag(InstanceTags.POOL_NAME_KEY), "minionPool"); + assertEquals(instanceTags.getTag(InstanceTags.GROUP_ID_KEY), "0"); + } + + @Test + public void testKeyValuePairs() { + InstanceTags instanceTags = InstanceTags.fromHelixTag("instance", "key1:value1;key2:value2;key3:value3"); + assertEquals(instanceTags.getInstanceName(), "instance"); + assertEquals(instanceTags.getTag("key1"), "value1"); + assertEquals(instanceTags.getTag("key2"), "value2"); + assertEquals(instanceTags.getTag("key3"), "value3"); + } + + @Test + public void testIllegalHelixTag() { + try { + InstanceTags.fromHelixTag("instance", "illegalRole_untagged"); + fail(); + } catch (IllegalArgumentException e) { + // Expected + } + + try { + InstanceTags.fromHelixTag("instance", "somePool_ILLEGALROLE"); + fail(); + } catch (IllegalArgumentException e) { + // Expected + } + + try { + InstanceTags.fromHelixTag("instance", "illegal:key:value:pair;key:value"); + fail(); + } catch (IllegalArgumentException e) { + // Expected + } + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
