Return-Path: X-Original-To: apmail-qpid-commits-archive@www.apache.org Delivered-To: apmail-qpid-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 89BAC11E78 for ; Wed, 21 May 2014 11:05:44 +0000 (UTC) Received: (qmail 24928 invoked by uid 500); 21 May 2014 11:05:44 -0000 Delivered-To: apmail-qpid-commits-archive@qpid.apache.org Received: (qmail 24902 invoked by uid 500); 21 May 2014 11:05:44 -0000 Mailing-List: contact commits-help@qpid.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@qpid.apache.org Delivered-To: mailing list commits@qpid.apache.org Received: (qmail 24895 invoked by uid 99); 21 May 2014 11:05:44 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 21 May 2014 11:05:44 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 21 May 2014 11:05:42 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id E385B2388860; Wed, 21 May 2014 11:05:21 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1596536 - in /qpid/trunk/qpid/java: bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/ bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/ bdbstore/systests/src/main/java/org/apache/qpid/server/store/berk... Date: Wed, 21 May 2014 11:05:21 -0000 To: commits@qpid.apache.org From: kwall@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20140521110521.E385B2388860@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: kwall Date: Wed May 21 11:05:21 2014 New Revision: 1596536 URL: http://svn.apache.org/r1596536 Log: QPID-5715: [Java Broker] Make virtualhosts respect the states ACTIVE and STOPPED * Add state transition tests for BDBHA virtualhostnode / virtualhost * Prevent the BDBVHN activating the VH (this is now a responsibility of attain desired state) * BDBHARemoteReplicationNode use state UNAVAILABLE in the case where the remote node is not MASTER or REPLICA. Work by Andrew MacBean and me. Modified: qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeImpl.java qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java qpid/trunk/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeRestTest.java qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostNodeRestTest.java Modified: qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeImpl.java URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeImpl.java?rev=1596536&r1=1596535&r2=1596536&view=diff ============================================================================== --- qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeImpl.java (original) +++ qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeImpl.java Wed May 21 11:05:21 2014 @@ -21,12 +21,14 @@ package org.apache.qpid.server.virtualhostnode.berkeleydb; +import static com.sleepycat.je.rep.ReplicatedEnvironment.State.MASTER; +import static com.sleepycat.je.rep.ReplicatedEnvironment.State.REPLICA; + import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import com.sleepycat.je.rep.MasterStateException; -import com.sleepycat.je.rep.ReplicatedEnvironment; import org.apache.log4j.Logger; import org.apache.qpid.server.configuration.IllegalConfigurationException; @@ -103,7 +105,7 @@ public class BDBHARemoteReplicationNodeI super.deleted(); } - @StateTransition(currentState = {State.ACTIVE, State.STOPPED}, desiredState = State.DELETED) + @StateTransition(currentState = {State.ACTIVE, State.UNAVAILABLE}, desiredState = State.DELETED) private void doDelete() { String nodeName = getName(); @@ -159,13 +161,13 @@ public class BDBHARemoteReplicationNodeI if (changedAttributes.contains(ROLE)) { String currentRole = getRole(); - if (!ReplicatedEnvironment.State.REPLICA.name().equals(currentRole)) + if (!REPLICA.name().equals(currentRole)) { throw new IllegalArgumentException("Cannot transfer mastership when not a replica"); } - if (!ReplicatedEnvironment.State.MASTER.name().equals(((BDBHARemoteReplicationNode)proxyForValidation).getRole())) + if (!MASTER.name().equals(((BDBHARemoteReplicationNode)proxyForValidation).getRole())) { - throw new IllegalArgumentException("Changing role to other value then " + ReplicatedEnvironment.State.MASTER.name() + " is unsupported"); + throw new IllegalArgumentException("Changing role to other value then " + MASTER.name() + " is unsupported"); } } @@ -183,6 +185,7 @@ public class BDBHARemoteReplicationNodeI void setRole(String role) { _role = role; + updateModelStateFromRole(role); } void setJoinTime(long joinTime) @@ -195,4 +198,15 @@ public class BDBHARemoteReplicationNodeI _lastTransactionId = lastTransactionId; } + private void updateModelStateFromRole(final String role) + { + State currentState = _state.get(); + if (currentState == State.DELETED) + { + return; + } + + boolean isActive = MASTER.name().equals(role) || REPLICA.name().equals(role); + _state.compareAndSet(currentState, isActive ? State.ACTIVE : State.UNAVAILABLE); + } } Modified: qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java?rev=1596536&r1=1596535&r2=1596536&view=diff ============================================================================== --- qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java (original) +++ qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java Wed May 21 11:05:21 2014 @@ -330,7 +330,7 @@ public class BDBHAVirtualHostNodeImpl ex } } - @StateTransition( currentState = { State.ACTIVE, State.ERRORED }, desiredState = State.STOPPED ) + @StateTransition( currentState = { State.UNINITIALIZED, State.ACTIVE, State.ERRORED }, desiredState = State.STOPPED ) protected void doStop() { try @@ -441,7 +441,6 @@ public class BDBHAVirtualHostNodeImpl ex } }); } - host.start(); } catch (Exception e) @@ -707,6 +706,12 @@ public class BDBHAVirtualHostNodeImpl ex } @Override + protected void onCreate() + { + // Do not persist replica virtualhost + } + + @Override protected C addChild(final Class childClass, final Map attributes, final ConfiguredObject... otherParents) Modified: qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java?rev=1596536&r1=1596535&r2=1596536&view=diff ============================================================================== --- qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java (original) +++ qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java Wed May 21 11:05:21 2014 @@ -143,16 +143,11 @@ public class BDBHAVirtualHostNodeTest ex VirtualHostNode node = createHaVHN(attributes); final CountDownLatch virtualHostAddedLatch = new CountDownLatch(1); - final CountDownLatch virtualHostStateChangeLatch = new CountDownLatch(1); node.addChangeListener(new ConfigurationChangeListener() { @Override public void stateChanged(ConfiguredObject object, State oldState, State newState) { - if (object instanceof VirtualHost) - { - virtualHostStateChangeLatch.countDown(); - } } @Override @@ -195,7 +190,6 @@ public class BDBHAVirtualHostNodeTest ex assertEquals("Unexpected JE replication stream timeout", repStreamTimeout, replicationConfig.getConfigParam(ReplicationConfig.REP_STREAM_TIMEOUT)); assertTrue("Virtual host child has not been added", virtualHostAddedLatch.await(30, TimeUnit.SECONDS)); - assertTrue("Virtual host child has not had a state change", virtualHostStateChangeLatch.await(30, TimeUnit.SECONDS)); VirtualHost virtualHost = node.getVirtualHost(); assertNotNull("Virtual host child was not added", virtualHost); assertEquals("Unexpected virtual host name", groupName, virtualHost.getName()); Modified: qpid/trunk/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeRestTest.java URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeRestTest.java?rev=1596536&r1=1596535&r2=1596536&view=diff ============================================================================== --- qpid/trunk/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeRestTest.java (original) +++ qpid/trunk/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeRestTest.java Wed May 21 11:05:21 2014 @@ -29,12 +29,16 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.servlet.http.HttpServletResponse; + +import org.apache.qpid.server.model.RemoteReplicationNode; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacade; import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHARemoteReplicationNode; import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNode; +import org.apache.qpid.systest.rest.Asserts; import org.apache.qpid.systest.rest.QpidRestTestCase; import org.apache.qpid.test.utils.TestBrokerConfiguration; import org.apache.qpid.util.FileUtils; @@ -106,6 +110,69 @@ public class BDBHAVirtualHostNodeRestTes assertRemoteNodes(NODE1, NODE2, NODE3); } + public void testMutateStateOfOneNode() throws Exception + { + createHANode(NODE1, _node1HaPort, _node1HaPort); + createHANode(NODE2, _node2HaPort, _node1HaPort); + createHANode(NODE3, _node3HaPort, _node1HaPort); + + String node1Url = _baseNodeRestUrl + NODE1; + String node2Url = _baseNodeRestUrl + NODE2; + String node3Url = _baseNodeRestUrl + NODE3; + + assertActualAndDesiredStates(node1Url, "ACTIVE", "ACTIVE"); + assertActualAndDesiredStates(node2Url, "ACTIVE", "ACTIVE"); + assertActualAndDesiredStates(node3Url, "ACTIVE", "ACTIVE"); + + mutateDesiredState(node1Url, "STOPPED"); + + assertActualAndDesiredStates(node1Url, "STOPPED", "STOPPED"); + assertActualAndDesiredStates(node2Url, "ACTIVE", "ACTIVE"); + assertActualAndDesiredStates(node3Url, "ACTIVE", "ACTIVE"); + + List> remoteNodes = getRestTestHelper().getJsonAsList("replicationnode/" + NODE2); + assertEquals("Unexpected number of remote nodes on " + NODE2, 2, remoteNodes.size()); + + Map remoteNode1 = findRemoteNodeByName(remoteNodes, NODE1); + + assertEquals("Node 1 observed from node 2 is in the wrong state", + "UNAVAILABLE", remoteNode1.get(BDBHARemoteReplicationNode.STATE)); + assertEquals("Node 1 observed from node 2 has the wrong role", + "UNKNOWN", remoteNode1.get(BDBHARemoteReplicationNode.ROLE)); + + } + + public void testNewMasterElectedWhenVirtualHostIsStopped() throws Exception + { + createHANode(NODE1, _node1HaPort, _node1HaPort); + createHANode(NODE2, _node2HaPort, _node1HaPort); + createHANode(NODE3, _node3HaPort, _node1HaPort); + + String node1Url = _baseNodeRestUrl + NODE1; + String node2Url = _baseNodeRestUrl + NODE2; + String node3Url = _baseNodeRestUrl + NODE3; + + assertActualAndDesiredStates(node1Url, "ACTIVE", "ACTIVE"); + assertActualAndDesiredStates(node2Url, "ACTIVE", "ACTIVE"); + assertActualAndDesiredStates(node3Url, "ACTIVE", "ACTIVE"); + + // Put virtualhost in STOPPED state + String virtualHostRestUrl = "virtualhost/" + NODE1 + "/" + _hostName; + assertActualAndDesiredStates(virtualHostRestUrl, "ACTIVE", "ACTIVE"); + mutateDesiredState(virtualHostRestUrl, "STOPPED"); + assertActualAndDesiredStates(virtualHostRestUrl, "STOPPED", "STOPPED"); + + // Now stop node 1 to cause an election between nodes 2 & 3 + mutateDesiredState(node1Url, "STOPPED"); + assertActualAndDesiredStates(node1Url, "STOPPED", "STOPPED"); + + Map newMasterData = awaitNewMaster(node2Url, node3Url); + + //Check the virtual host of the new master is in the stopped state + String newMasterVirtualHostRestUrl = "virtualhost/" + newMasterData.get(BDBHAVirtualHostNode.NAME) + "/" + _hostName; + assertActualAndDesiredStates(newMasterVirtualHostRestUrl, "STOPPED", "STOPPED"); + } + public void testDeleteReplicaNode() throws Exception { createHANode(NODE1, _node1HaPort, _node1HaPort); @@ -128,6 +195,7 @@ public class BDBHAVirtualHostNodeRestTes { Thread.sleep(100l); } + counter++; } assertEquals("Unexpected number of remote nodes on " + NODE1, 1, data.size()); } @@ -167,6 +235,7 @@ public class BDBHAVirtualHostNodeRestTes { Thread.sleep(100l); } + counter++; } assertEquals("Unexpected number of remote nodes on " + NODE2, 1, data.size()); } @@ -259,4 +328,61 @@ public class BDBHAVirtualHostNodeRestTes assertNotNull("Node " + name + " has unexpected joinTime", joinTime); assertTrue("Node " + name + " has unexpected joinTime " + joinTime, joinTime > 0); } + + private void assertActualAndDesiredStates(final String restUrl, + final String expectedDesiredState, + final String expectedActualState) throws IOException + { + Map objectData = getRestTestHelper().getJsonAsSingletonList(restUrl); + Asserts.assertActualAndDesiredState(expectedDesiredState, expectedActualState, objectData); + } + + private void mutateDesiredState(final String restUrl, final String newState) throws IOException + { + Map newAttributes = new HashMap(); + newAttributes.put(VirtualHostNode.DESIRED_STATE, newState); + + getRestTestHelper().submitRequest(restUrl, "PUT", newAttributes, HttpServletResponse.SC_OK); + } + + private Map findRemoteNodeByName(final List> remoteNodes, final String nodeName) + { + Map foundNode = null; + for (Map remoteNode : remoteNodes) + { + if (nodeName.equals(remoteNode.get(RemoteReplicationNode.NAME))) + { + foundNode = remoteNode; + break; + } + } + assertNotNull("Could not find node with name " + nodeName + " amongst remote nodes."); + return foundNode; + } + + private Map awaitNewMaster(final String... nodeUrls) + throws IOException, InterruptedException + { + Map newMasterData = null; + int counter = 0; + while (newMasterData == null && counter < 50) + { + for(String nodeUrl: nodeUrls) + { + Map nodeData = getRestTestHelper().getJsonAsSingletonList(nodeUrl); + if ("MASTER".equals(nodeData.get(BDBHAVirtualHostNode.ROLE))) + { + newMasterData = nodeData; + break; + } + } + if (newMasterData == null) + { + Thread.sleep(100l); + counter++; + } + } + assertNotNull("Could not find new master", newMasterData); + return newMasterData; + } } Modified: qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java?rev=1596536&r1=1596535&r2=1596536&view=diff ============================================================================== --- qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java (original) +++ qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java Wed May 21 11:05:21 2014 @@ -1209,7 +1209,7 @@ public abstract class AbstractVirtualHos return _housekeepingThreadCount; } - @StateTransition( currentState = { State.ACTIVE, State.ERRORED, State.UNINITIALIZED }, desiredState = State.STOPPED ) + @StateTransition( currentState = { State.UNINITIALIZED, State.ACTIVE, State.ERRORED }, desiredState = State.STOPPED ) protected void doStop() { closeChildren(); @@ -1219,7 +1219,7 @@ public abstract class AbstractVirtualHos } - @StateTransition( currentState = { State.ACTIVE, State.QUIESCED, State.ERRORED }, desiredState = State.DELETED ) + @StateTransition( currentState = { State.ACTIVE, State.ERRORED }, desiredState = State.DELETED ) private void doDelete() { if(_deleted.compareAndSet(false,true)) @@ -1400,7 +1400,7 @@ public abstract class AbstractVirtualHos getDurableConfigurationStore().create(new ConfiguredObjectRecordImpl(record.getId(), record.getType(), record.getAttributes())); } - @StateTransition( currentState = {State.UNINITIALIZED, State.ERRORED, State.QUIESCED, State.STOPPED}, desiredState = State.ACTIVE ) + @StateTransition( currentState = { State.UNINITIALIZED, State.STOPPED, State.ERRORED }, desiredState = State.ACTIVE ) private void onActivate() { _houseKeepingTasks = new ScheduledThreadPoolExecutor(getHousekeepingThreadCount()); Modified: qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostNodeRestTest.java URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostNodeRestTest.java?rev=1596536&r1=1596535&r2=1596536&view=diff ============================================================================== --- qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostNodeRestTest.java (original) +++ qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostNodeRestTest.java Wed May 21 11:05:21 2014 @@ -94,10 +94,10 @@ public class VirtualHostNodeRestTest ex assertActualAndDesireStates(restUrl, "ACTIVE", "ACTIVE"); - mutateVirtualHostDesiredState(restUrl, "STOPPED"); + mutateVirtualHostNodeDesiredState(restUrl, "STOPPED"); assertActualAndDesireStates(restUrl, "STOPPED", "STOPPED"); - mutateVirtualHostDesiredState(restUrl, "ACTIVE"); + mutateVirtualHostNodeDesiredState(restUrl, "ACTIVE"); assertActualAndDesireStates(restUrl, "ACTIVE", "ACTIVE"); } @@ -145,7 +145,7 @@ public class VirtualHostNodeRestTest ex Asserts.assertActualAndDesiredState(expectedDesiredState, expectedActualState, virtualhostNode); } - private void mutateVirtualHostDesiredState(final String restUrl, final String newState) throws IOException + private void mutateVirtualHostNodeDesiredState(final String restUrl, final String newState) throws IOException { Map newAttributes = new HashMap(); newAttributes.put(VirtualHostNode.DESIRED_STATE, newState); --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org For additional commands, e-mail: commits-help@qpid.apache.org