| package org.apache.helix.model; |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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. |
| */ |
| |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.TreeMap; |
| |
| import org.apache.helix.PropertyKey.Builder; |
| import org.apache.helix.TestHelper; |
| import org.apache.helix.zookeeper.datamodel.ZNRecord; |
| import org.apache.helix.ZkUnitTestBase; |
| import org.apache.helix.manager.zk.ZKHelixDataAccessor; |
| import org.apache.helix.manager.zk.ZkBaseDataAccessor; |
| import org.apache.helix.model.ClusterConstraints.ConstraintAttribute; |
| import org.apache.helix.model.ClusterConstraints.ConstraintType; |
| import org.apache.helix.model.Message.MessageType; |
| import org.testng.Assert; |
| import org.testng.annotations.Test; |
| |
| public class TestConstraint extends ZkUnitTestBase { |
| |
| @Test |
| public void testMsgConstraint() { |
| String className = getShortClassName(); |
| System.out.println("START testMsgConstraint() at " + new Date(System.currentTimeMillis())); |
| |
| String clusterName = "CLUSTER_" + className + "_msg"; |
| TestHelper.setupEmptyCluster(_gZkClient, clusterName); |
| ZNRecord record = new ZNRecord("testMsgConstraint"); |
| |
| // constraint0: |
| // "MESSAGE_TYPE=STATE_TRANSITION,CONSTRAINT_VALUE=ANY" |
| record.setMapField("constraint0", new TreeMap<String, String>()); |
| record.getMapField("constraint0").put("MESSAGE_TYPE", "STATE_TRANSITION"); |
| record.getMapField("constraint0").put("CONSTRAINT_VALUE", "ANY"); |
| ConstraintItem constraint0 = new ConstraintItem(record.getMapField("constraint0")); |
| |
| // constraint1: |
| // "MESSAGE_TYPE=STATE_TRANSITION,TRANSITION=OFFLINE-SLAVE,CONSTRAINT_VALUE=ANY" |
| record.setMapField("constraint1", new TreeMap<String, String>()); |
| record.getMapField("constraint1").put("MESSAGE_TYPE", "STATE_TRANSITION"); |
| record.getMapField("constraint1").put("TRANSITION", "OFFLINE-SLAVE"); |
| record.getMapField("constraint1").put("CONSTRAINT_VALUE", "50"); |
| ConstraintItem constraint1 = new ConstraintItem(record.getMapField("constraint1")); |
| |
| // constraint2: |
| // "MESSAGE_TYPE=STATE_TRANSITION,TRANSITION=OFFLINE-SLAVE,INSTANCE=.*,RESOURCE=TestDB,CONSTRAINT_VALUE=2"; |
| record.setMapField("constraint2", new TreeMap<String, String>()); |
| record.getMapField("constraint2").put("MESSAGE_TYPE", "STATE_TRANSITION"); |
| record.getMapField("constraint2").put("TRANSITION", "OFFLINE-SLAVE"); |
| record.getMapField("constraint2").put("INSTANCE", ".*"); |
| record.getMapField("constraint2").put("RESOURCE", "TestDB"); |
| record.getMapField("constraint2").put("CONSTRAINT_VALUE", "2"); |
| ConstraintItem constraint2 = new ConstraintItem(record.getMapField("constraint2")); |
| |
| // constraint3: |
| // "MESSAGE_TYPE=STATE_TRANSITION,TRANSITION=OFFLINE-SLAVE,INSTANCE=localhost_12918,RESOURCE=.*,CONSTRAINT_VALUE=1"; |
| record.setMapField("constraint3", new TreeMap<String, String>()); |
| record.getMapField("constraint3").put("MESSAGE_TYPE", "STATE_TRANSITION"); |
| record.getMapField("constraint3").put("TRANSITION", "OFFLINE-SLAVE"); |
| record.getMapField("constraint3").put("INSTANCE", "localhost_12919"); |
| record.getMapField("constraint3").put("RESOURCE", ".*"); |
| record.getMapField("constraint3").put("CONSTRAINT_VALUE", "1"); |
| ConstraintItem constraint3 = new ConstraintItem(record.getMapField("constraint3")); |
| |
| // constraint4: |
| // "MESSAGE_TYPE=STATE_TRANSITION,TRANSITION=OFFLINE-SLAVE,INSTANCE=.*,RESOURCE=.*,CONSTRAINT_VALUE=10" |
| record.setMapField("constraint4", new TreeMap<String, String>()); |
| record.getMapField("constraint4").put("MESSAGE_TYPE", "STATE_TRANSITION"); |
| record.getMapField("constraint4").put("TRANSITION", "OFFLINE-SLAVE"); |
| record.getMapField("constraint4").put("INSTANCE", ".*"); |
| record.getMapField("constraint4").put("RESOURCE", ".*"); |
| record.getMapField("constraint4").put("CONSTRAINT_VALUE", "10"); |
| ConstraintItem constraint4 = new ConstraintItem(record.getMapField("constraint4")); |
| |
| // constraint5: |
| // "MESSAGE_TYPE=STATE_TRANSITION,TRANSITION=OFFLINE-SLAVE,INSTANCE=localhost_12918,RESOURCE=TestDB,CONSTRAINT_VALUE=5" |
| record.setMapField("constraint5", new TreeMap<String, String>()); |
| record.getMapField("constraint5").put("MESSAGE_TYPE", "STATE_TRANSITION"); |
| record.getMapField("constraint5").put("TRANSITION", "OFFLINE-SLAVE"); |
| record.getMapField("constraint5").put("INSTANCE", "localhost_12918"); |
| record.getMapField("constraint5").put("RESOURCE", "TestDB"); |
| record.getMapField("constraint5").put("CONSTRAINT_VALUE", "5"); |
| ConstraintItem constraint5 = new ConstraintItem(record.getMapField("constraint5")); |
| |
| ZKHelixDataAccessor accessor = |
| new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_gZkClient)); |
| Builder keyBuilder = accessor.keyBuilder(); |
| |
| accessor.setProperty(keyBuilder.constraint(ConstraintType.MESSAGE_CONSTRAINT.toString()), |
| new ClusterConstraints(record)); |
| |
| record = |
| accessor.getProperty(keyBuilder.constraint(ConstraintType.MESSAGE_CONSTRAINT.toString())) |
| .getRecord(); |
| ClusterConstraints constraint = new ClusterConstraints(record); |
| // System.out.println("constraint: " + constraint); |
| |
| // message1 |
| Message msg1 = |
| createMessage(MessageType.STATE_TRANSITION, "msgId-001", "OFFLINE", "SLAVE", "TestDB", |
| "localhost_12918"); |
| |
| Map<ConstraintAttribute, String> msgAttr = ClusterConstraints.toConstraintAttributes(msg1); |
| Set<ConstraintItem> matches = constraint.match(msgAttr); |
| System.out.println(msg1 + " matches(" + matches.size() + "): " + matches); |
| Assert.assertEquals(matches.size(), 5); |
| Assert.assertTrue(contains(matches, constraint0)); |
| Assert.assertTrue(contains(matches, constraint1)); |
| Assert.assertTrue(contains(matches, constraint2)); |
| Assert.assertTrue(contains(matches, constraint4)); |
| Assert.assertTrue(contains(matches, constraint5)); |
| |
| // message2 |
| Message msg2 = |
| createMessage(MessageType.STATE_TRANSITION, "msgId-002", "OFFLINE", "SLAVE", "TestDB", |
| "localhost_12919"); |
| |
| msgAttr = ClusterConstraints.toConstraintAttributes(msg2); |
| matches = constraint.match(msgAttr); |
| System.out.println(msg2 + " matches(" + matches.size() + "): " + matches); |
| Assert.assertEquals(matches.size(), 5); |
| Assert.assertTrue(contains(matches, constraint0)); |
| Assert.assertTrue(contains(matches, constraint1)); |
| Assert.assertTrue(contains(matches, constraint2)); |
| Assert.assertTrue(contains(matches, constraint3)); |
| Assert.assertTrue(contains(matches, constraint4)); |
| |
| System.out.println("END testMsgConstraint() at " + new Date(System.currentTimeMillis())); |
| } |
| |
| @Test |
| public void testStateConstraint() { |
| String className = getShortClassName(); |
| System.out.println("START testStateConstraint() at " + new Date(System.currentTimeMillis())); |
| |
| String clusterName = "CLUSTER_" + className + "_state"; |
| TestHelper.setupEmptyCluster(_gZkClient, clusterName); |
| ZNRecord record = new ZNRecord("testStateConstraint"); |
| |
| // constraint0: |
| // "STATE=MASTER,CONSTRAINT_VALUE=1" |
| record.setMapField("constraint0", new TreeMap<String, String>()); |
| record.getMapField("constraint0").put("STATE", "MASTER"); |
| record.getMapField("constraint0").put("CONSTRAINT_VALUE", "1"); |
| ConstraintItem constraint0 = new ConstraintItem(record.getMapField("constraint0")); |
| |
| // constraint1: |
| // "STATE=MASTER,RESOURCE=TestDB,CONSTRAINT_VALUE=5" |
| record.setMapField("constraint1", new TreeMap<String, String>()); |
| record.getMapField("constraint1").put("STATE", "MASTER"); |
| record.getMapField("constraint1").put("RESOURCE", "TestDB"); |
| record.getMapField("constraint1").put("CONSTRAINT_VALUE", "1"); |
| ConstraintItem constraint1 = new ConstraintItem(record.getMapField("constraint1")); |
| |
| // constraint2: |
| // "STATE=MASTER,RESOURCE=.*,CONSTRAINT_VALUE=2" |
| record.setMapField("constraint2", new TreeMap<String, String>()); |
| record.getMapField("constraint2").put("STATE", "MASTER"); |
| record.getMapField("constraint2").put("RESOURCE", ".*"); |
| record.getMapField("constraint2").put("CONSTRAINT_VALUE", "2"); |
| ConstraintItem constraint2 = new ConstraintItem(record.getMapField("constraint2")); |
| |
| ZKHelixDataAccessor accessor = |
| new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_gZkClient)); |
| Builder keyBuilder = accessor.keyBuilder(); |
| |
| accessor.setProperty(keyBuilder.constraint(ConstraintType.STATE_CONSTRAINT.toString()), |
| new ClusterConstraints(record)); |
| |
| record = |
| accessor.getProperty(keyBuilder.constraint(ConstraintType.STATE_CONSTRAINT.toString())) |
| .getRecord(); |
| ClusterConstraints constraint = new ClusterConstraints(record); |
| // System.out.println("constraint: " + constraint); |
| |
| // state1: hit rule2 |
| Map<ConstraintAttribute, String> stateAttr1 = new HashMap<ConstraintAttribute, String>(); |
| stateAttr1.put(ConstraintAttribute.STATE, "MASTER"); |
| stateAttr1.put(ConstraintAttribute.RESOURCE, "TestDB"); |
| |
| Set<ConstraintItem> matches = constraint.match(stateAttr1); |
| System.out.println(stateAttr1 + " matches(" + matches.size() + "): " + matches); |
| Assert.assertEquals(matches.size(), 3); |
| Assert.assertTrue(contains(matches, constraint0)); |
| Assert.assertTrue(contains(matches, constraint1)); |
| Assert.assertTrue(contains(matches, constraint2)); |
| |
| // matches = selectConstraints(matches, stateAttr1); |
| // System.out.println(stateAttr1 + " matches(" + matches.size() + "): " + matches); |
| // Assert.assertEquals(matches.size(), 2); |
| // Assert.assertTrue(contains(matches, constraint0)); |
| // Assert.assertTrue(contains(matches, constraint1)); |
| |
| // state2: not hit any rules |
| Map<ConstraintAttribute, String> stateAttr2 = new HashMap<ConstraintAttribute, String>(); |
| stateAttr2.put(ConstraintAttribute.STATE, "MASTER"); |
| stateAttr2.put(ConstraintAttribute.RESOURCE, "MyDB"); |
| |
| matches = constraint.match(stateAttr2); |
| System.out.println(stateAttr2 + " matches(" + matches.size() + "): " + matches); |
| Assert.assertEquals(matches.size(), 2); |
| Assert.assertTrue(contains(matches, constraint0)); |
| Assert.assertTrue(contains(matches, constraint2)); |
| |
| // matches = selectConstraints(matches, stateAttr2); |
| // System.out.println(stateAttr2 + " matches(" + matches.size() + "): " + matches); |
| // Assert.assertEquals(matches.size(), 2); |
| // Assert.assertTrue(contains(matches, constraint0)); |
| // Assert.assertTrue(contains(matches, constraint2)); |
| |
| deleteCluster(clusterName); |
| System.out.println("END testStateConstraint() at " + new Date(System.currentTimeMillis())); |
| } |
| |
| private boolean contains(Set<ConstraintItem> constraints, ConstraintItem constraint) { |
| for (ConstraintItem item : constraints) { |
| if (item.toString().equals(constraint.toString())) { |
| return true; |
| } |
| } |
| return false; |
| } |
| } |