You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ma...@apache.org on 2014/07/14 12:26:17 UTC

svn commit: r1610379 [1/2] - in /qpid/trunk/qpid/java: bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/ bdbstore/src/test/java/org/apache/qpid/server/s...

Author: macbean
Date: Mon Jul 14 10:26:17 2014
New Revision: 1610379

URL: http://svn.apache.org/r1610379
Log:
QPID-5891: [Java Broker] Add BDB HA operational logging functionality

Work completed by Alex Rudyy <or...@apache.org> and me.

Added:
    qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/NoopConfigurationChangeListener.java
    qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeOperationalLoggingTest.java
    qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java
    qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/HighAvailabilityMessages.java
    qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/HighAvailability_logmessages.properties
    qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/subjects/VirtualHostNodeLogSubject.java
Modified:
    qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java
    qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicationGroupListener.java
    qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNode.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/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacadeTest.java
    qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/subjects/LogSubjectFormat.java
    qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java

Modified: qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java?rev=1610379&r1=1610378&r2=1610379&view=diff
==============================================================================
--- qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java (original)
+++ qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java Mon Jul 14 10:26:17 2014
@@ -306,7 +306,18 @@ public class ReplicatedEnvironmentFacade
     @Override
     public DatabaseException handleDatabaseException(String contextMessage, final DatabaseException dbe)
     {
-        boolean restart = (dbe instanceof InsufficientReplicasException || dbe instanceof InsufficientAcksException || dbe instanceof RestartRequiredException);
+        boolean noMajority = dbe instanceof InsufficientReplicasException || dbe instanceof InsufficientAcksException;
+
+        if (noMajority)
+        {
+            ReplicationGroupListener listener = _replicationGroupListener.get();
+            if (listener != null)
+            {
+                listener.onNoMajority();
+            }
+        }
+
+        boolean restart = (noMajority || dbe instanceof RestartRequiredException);
         if (restart)
         {
             tryToRestartEnvironment(dbe);
@@ -951,7 +962,6 @@ public class ReplicatedEnvironmentFacade
         {
             connectToHelperNodeAndCheckPermittedHosts(helperNodeName, helperHostPort, hostPort);
         }
-
         Map<String, String> replicationEnvironmentParameters = new HashMap<>(ReplicatedEnvironmentFacade.REPCONFIG_DEFAULTS);
         replicationEnvironmentParameters.putAll(_configuration.getReplicationParameters());
 
@@ -1107,10 +1117,6 @@ public class ReplicatedEnvironmentFacade
             }
             _realMessageStoreDurability = new Durability(localTransactionSynchronizationPolicy, remoteTransactionSynchronizationPolicy, replicaAcknowledgmentPolicy);
         }
-        else
-        {
-            throw new IllegalStateException("Message store durability is already set to " + _messageStoreDurability.get());
-        }
     }
 
     public void setPermittedNodes(Collection<String> permittedNodes)

Modified: qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicationGroupListener.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicationGroupListener.java?rev=1610379&r1=1610378&r2=1610379&view=diff
==============================================================================
--- qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicationGroupListener.java (original)
+++ qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicationGroupListener.java Mon Jul 14 10:26:17 2014
@@ -53,4 +53,6 @@ public interface ReplicationGroupListene
      */
     void onIntruderNode(ReplicationNode node);
 
+    void onNoMajority();
+
 }

Modified: qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNode.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNode.java?rev=1610379&r1=1610378&r2=1610379&view=diff
==============================================================================
--- qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNode.java (original)
+++ qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNode.java Mon Jul 14 10:26:17 2014
@@ -56,7 +56,7 @@ public interface BDBHAVirtualHostNode<X 
     @ManagedAttribute(defaultValue = "0")
     int getQuorumOverride();
 
-    @ManagedAttribute(persist = false)
+    @ManagedAttribute(persist = false, defaultValue = "UNKNOWN")
     String getRole();
 
     @DerivedAttribute

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=1610379&r1=1610378&r2=1610379&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 Mon Jul 14 10:26:17 2014
@@ -47,6 +47,7 @@ import org.apache.log4j.Logger;
 
 import org.apache.qpid.server.configuration.updater.Task;
 import org.apache.qpid.server.logging.messages.ConfigStoreMessages;
+import org.apache.qpid.server.logging.messages.HighAvailabilityMessages;
 import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.BrokerModel;
 import org.apache.qpid.server.model.ConfiguredObject;
@@ -247,6 +248,13 @@ public class BDBHAVirtualHostNodeImpl ex
         return (BDBConfigurationStore) super.getConfigurationStore();
     }
 
+    @Override
+    public void onCreate()
+    {
+        super.onCreate();
+        getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.ADDED(getName(), getGroupName()));
+    }
+
     protected ReplicatedEnvironmentFacade getReplicatedEnvironmentFacade()
     {
         return _environmentFacade.get();
@@ -268,6 +276,8 @@ public class BDBHAVirtualHostNodeImpl ex
 
         getConfigurationStore().openConfigurationStore(this);
 
+        getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.ATTACHED(getName(), getGroupName(), getRole()));
+
         getEventLogger().message(getConfigurationStoreLogSubject(), ConfigStoreMessages.CREATED());
         getEventLogger().message(getConfigurationStoreLogSubject(), ConfigStoreMessages.STORE_LOCATION(getStorePath()));
 
@@ -279,7 +289,7 @@ public class BDBHAVirtualHostNodeImpl ex
 
         if (_environmentFacade.compareAndSet(null, environmentFacade))
         {
-            environmentFacade.setStateChangeListener(new BDBHAMessageStoreStateChangeListener());
+            environmentFacade.setStateChangeListener(new EnvironmentStateChangeListener());
             environmentFacade.setReplicationGroupListener(new RemoteNodesDiscoverer());
         }
     }
@@ -294,13 +304,30 @@ public class BDBHAVirtualHostNodeImpl ex
         finally
         {
             stopEnvironment();
+
+            //Perhaps, having STOPPED operational logging could be sufficient. However, on START we still will be seeing 2 logs: ATTACHED and STARTED
+            getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.DETACHED(getName(), getGroupName()));
+            getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.STOPPED(getName(), getGroupName()));
+        }
+    }
+
+    @StateTransition( currentState = { State.UNINITIALIZED, State.STOPPED, State.ERRORED }, desiredState = State.ACTIVE )
+    protected void doActivate()
+    {
+        try
+        {
+            super.doActivate();
+        }
+        finally
+        {
+            getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.STARTED(getName(), getGroupName()));
         }
     }
 
     private void stopEnvironment()
     {
         ReplicatedEnvironmentFacade environmentFacade = getReplicatedEnvironmentFacade();
-        if (_environmentFacade.compareAndSet(environmentFacade, null))
+        if (environmentFacade != null && _environmentFacade.compareAndSet(environmentFacade, null))
         {
             environmentFacade.close();
         }
@@ -311,6 +338,7 @@ public class BDBHAVirtualHostNodeImpl ex
     {
         Set<InetSocketAddress> helpers = getRemoteNodeAddresses();
         super.doDelete();
+        getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.DELETED(getName(), getGroupName()));
         if (getState() == State.DELETED && !helpers.isEmpty())
         {
             try
@@ -362,11 +390,8 @@ public class BDBHAVirtualHostNodeImpl ex
         }
         finally
         {
-            ReplicatedEnvironmentFacade environmentFacade = getReplicatedEnvironmentFacade();
-            if (environmentFacade != null && _environmentFacade.compareAndSet(environmentFacade, null))
-            {
-                environmentFacade.close();
-            }
+            stopEnvironment();
+            getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.DETACHED(getName(), getGroupName()));
         }
     }
 
@@ -463,7 +488,7 @@ public class BDBHAVirtualHostNodeImpl ex
         }
     }
 
-    private class BDBHAMessageStoreStateChangeListener implements StateChangeListener
+    private class EnvironmentStateChangeListener implements StateChangeListener
     {
         @Override
         public void stateChange(StateChangeEvent stateChangeEvent) throws RuntimeException
@@ -475,25 +500,33 @@ public class BDBHAVirtualHostNodeImpl ex
                 LOGGER.info("Received BDB event indicating transition to state " + state);
             }
 
-            switch (state)
+            try
             {
-            case MASTER:
-                onMaster();
-                break;
-            case REPLICA:
-                onReplica();
-                break;
-            case DETACHED:
-                onDetached();
-                break;
-            case UNKNOWN:
-                break;
-            default:
-                LOGGER.error("Unexpected state change: " + state);
-                throw new IllegalStateException("Unexpected state change: " + state);
+                switch (state)
+                {
+                    case MASTER:
+                        onMaster();
+                        break;
+                    case REPLICA:
+                        onReplica();
+                        break;
+                    case DETACHED:
+                        onDetached();
+                        break;
+                    case UNKNOWN:
+                        break;
+                    default:
+                        LOGGER.error("Unexpected state change: " + state);
+                }
+            }
+            finally
+            {
+                _lastReplicatedEnvironmentState.set(state);
+                String previousRole = _role;
+                attributeSet(ROLE, _role, state.name());
+                getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.ROLE_CHANGED(getName(),
+                        getGroupName(), previousRole, state.name()));
             }
-            _lastReplicatedEnvironmentState.set(state);
-            attributeSet(ROLE, _role, state.name());
         }
     }
 
@@ -507,10 +540,8 @@ public class BDBHAVirtualHostNodeImpl ex
             try
             {
                 environmentFacade.setPriority(_priority).get(MUTATE_JE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
-                if (LOGGER.isDebugEnabled())
-                {
-                    LOGGER.debug("Node priority changed. " + this);
-                }
+                getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.PRIORITY_CHANGED(getName(),
+                        getGroupName(), String.valueOf(_priority)));
             }
             catch (TimeoutException e)
             {
@@ -537,10 +568,8 @@ public class BDBHAVirtualHostNodeImpl ex
             try
             {
                 environmentFacade.setDesignatedPrimary(_designatedPrimary).get(MUTATE_JE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
-                if (LOGGER.isDebugEnabled())
-                {
-                    LOGGER.debug("Designated primary changed. " + this);
-                }
+                getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.DESIGNATED_PRIMARY_CHANGED(getName(),
+                        getGroupName(), String.valueOf(_designatedPrimary)));
             }
             catch (TimeoutException e)
             {
@@ -567,10 +596,8 @@ public class BDBHAVirtualHostNodeImpl ex
             try
             {
                 environmentFacade.setElectableGroupSizeOverride(_quorumOverride).get(MUTATE_JE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
-                if (LOGGER.isDebugEnabled())
-                {
-                    LOGGER.debug("Quorum override changed. " + this);
-                }
+                getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.QUORUM_OVERRIDE_CHANGED(getName(),
+                        getGroupName(), String.valueOf(_quorumOverride)));
             }
             catch (TimeoutException e)
             {
@@ -597,10 +624,7 @@ public class BDBHAVirtualHostNodeImpl ex
             try
             {
                 environmentFacade.transferMasterToSelfAsynchronously().get(MUTATE_JE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
-                if (LOGGER.isDebugEnabled())
-                {
-                    LOGGER.debug("Requested master transfer to self. " + this);
-                }
+                getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.TRANSFER_MASTER(getName(), getName(), getGroupName()));
             }
             catch (TimeoutException e)
             {
@@ -642,6 +666,7 @@ public class BDBHAVirtualHostNodeImpl ex
             BDBHARemoteReplicationNodeImpl remoteNode = new BDBHARemoteReplicationNodeImpl(BDBHAVirtualHostNodeImpl.this, nodeToAttributes(node), getReplicatedEnvironmentFacade());
             remoteNode.create();
             childAdded(remoteNode);
+            getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.ADDED(remoteNode.getName(), getGroupName()));
         }
 
         @Override
@@ -662,6 +687,8 @@ public class BDBHAVirtualHostNodeImpl ex
         {
             BDBHARemoteReplicationNodeImpl remoteNode = new BDBHARemoteReplicationNodeImpl(BDBHAVirtualHostNodeImpl.this, nodeToAttributes(node), getReplicatedEnvironmentFacade());
             remoteNode.open();
+
+            getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.ATTACHED(remoteNode.getName(), getGroupName(), String.valueOf(remoteNode.getState())));
         }
 
         @Override
@@ -684,6 +711,7 @@ public class BDBHAVirtualHostNodeImpl ex
             if (remoteNode != null)
             {
                 remoteNode.deleted();
+                getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.DELETED(remoteNode.getName(), getGroupName()));
             }
         }
 
@@ -693,6 +721,7 @@ public class BDBHAVirtualHostNodeImpl ex
             BDBHARemoteReplicationNodeImpl remoteNode = getChildByName(BDBHARemoteReplicationNodeImpl.class, node.getName());
             if (remoteNode != null)
             {
+                String currentRole = remoteNode.getRole();
                 if (nodeState == null)
                 {
                     remoteNode.setRole(ReplicatedEnvironment.State.UNKNOWN.name());
@@ -703,17 +732,25 @@ public class BDBHAVirtualHostNodeImpl ex
                     remoteNode.setLastTransactionId(nodeState.getCurrentTxnEndVLSN());
                     remoteNode.setRole(nodeState.getNodeState().name());
                 }
+
+                String newRole = remoteNode.getRole();
+                if (!newRole.equals(currentRole))
+                {
+                    getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.ROLE_CHANGED(remoteNode.getName(),
+                            getGroupName(), currentRole, newRole));
+                }
             }
         }
 
         @Override
         public void onIntruderNode(ReplicationNode node)
         {
+            String hostAndPort = node.getHostName() + ":" + node.getPort();
+            getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.INTRUDER_DETECTED(node.getName(), hostAndPort, getGroupName()));
+
             boolean inManagementMode = getParent(Broker.class).isManagementMode();
             if (inManagementMode)
             {
-                LOGGER.warn(String.format("Intruder replication node '%s' from '%s' is detected. Ignoring intruder in management mode",
-                        node.getName(), node.getHostName() + ":" + node.getPort() ));
                 BDBHARemoteReplicationNodeImpl remoteNode = getChildByName(BDBHARemoteReplicationNodeImpl.class, node.getName());
                 if (remoteNode == null)
                 {
@@ -723,7 +760,7 @@ public class BDBHAVirtualHostNodeImpl ex
             else
             {
                 LOGGER.error(String.format("Intruder node '%s' from '%s' is detected. Stopping down virtual host node '%s'",
-                        node.getName(), node.getHostName() + ":" + node.getPort(), BDBHAVirtualHostNodeImpl.this.toString() ));
+                        node.getName(), hostAndPort, BDBHAVirtualHostNodeImpl.this.toString() ));
 
                 getTaskExecutor().submit(new Task<Void>()
                 {
@@ -750,6 +787,12 @@ public class BDBHAVirtualHostNodeImpl ex
             }
         }
 
+        @Override
+        public void onNoMajority()
+        {
+            getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.MAJORITY_LOST(getName(), getGroupName()));
+        }
+
         private Map<String, Object> nodeToAttributes(ReplicationNode replicationNode)
         {
             Map<String, Object> attributes = new HashMap<String, Object>();

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=1610379&r1=1610378&r2=1610379&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 Mon Jul 14 10:26:17 2014
@@ -24,14 +24,10 @@ import static org.mockito.Mockito.when;
 
 import java.io.File;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -41,54 +37,30 @@ import com.sleepycat.je.rep.ReplicatedEn
 import com.sleepycat.je.rep.ReplicationConfig;
 
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
-import org.apache.qpid.server.configuration.updater.TaskExecutor;
-import org.apache.qpid.server.configuration.updater.TaskExecutorImpl;
-import org.apache.qpid.server.logging.LogMessage;
-import org.apache.qpid.server.logging.LogSubject;
-import org.apache.qpid.server.logging.MessageLogger;
-import org.apache.qpid.server.logging.messages.VirtualHostMessages;
-import org.apache.qpid.server.model.Broker;
-import org.apache.qpid.server.model.BrokerModel;
 import org.apache.qpid.server.model.ConfigurationChangeListener;
 import org.apache.qpid.server.model.ConfiguredObject;
-import org.apache.qpid.server.model.ConfiguredObjectFactory;
 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.DurableConfigurationStore;
-import org.apache.qpid.server.util.BrokerTestHelper;
 import org.apache.qpid.server.virtualhost.berkeleydb.BDBHAVirtualHost;
 import org.apache.qpid.server.virtualhost.berkeleydb.BDBHAVirtualHostImpl;
 import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHARemoteReplicationNode;
 import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHARemoteReplicationNodeImpl;
 import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNode;
+import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNodeTestHelper;
 import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNodeImpl;
 import org.apache.qpid.test.utils.QpidTestCase;
-import org.apache.qpid.util.FileUtils;
 
 public class BDBHAVirtualHostNodeTest extends QpidTestCase
 {
-
-    private Broker<?> _broker;
-    private File _bdbStorePath;
-    private TaskExecutor _taskExecutor;
-    private final ConfiguredObjectFactory _objectFactory = BrokerModel.getInstance().getObjectFactory();
-    private final Set<BDBHAVirtualHostNode<?>> _nodes = new HashSet<>();
-
+    private BDBHAVirtualHostNodeTestHelper _helper;
     @Override
     protected void setUp() throws Exception
     {
         super.setUp();
 
-        _broker = BrokerTestHelper.createBrokerMock();
-
-        _taskExecutor = new TaskExecutorImpl();
-        _taskExecutor.start();
-        when(_broker.getTaskExecutor()).thenReturn(_taskExecutor);
-
-        _bdbStorePath = new File(TMP_FOLDER, getTestName() + "." + System.currentTimeMillis());
-        _bdbStorePath.deleteOnExit();
+        _helper = new BDBHAVirtualHostNodeTestHelper(getTestName());
     }
 
     @Override
@@ -96,42 +68,17 @@ public class BDBHAVirtualHostNodeTest ex
     {
         try
         {
-            Exception firstException = null;
-            for (VirtualHostNode<?> node : _nodes)
-            {
-                try
-                {
-                    node.delete();
-                }
-                catch(Exception e)
-                {
-                    if (firstException != null)
-                    {
-                        firstException = e;
-                    }
-                }
-                if (firstException != null)
-                {
-                    throw firstException;
-                }
-            }
+            _helper.tearDown();
         }
         finally
         {
-            if (_taskExecutor != null)
-            {
-                _taskExecutor.stopImmediately();
-            }
-            if (_bdbStorePath != null)
-            {
-                FileUtils.delete(_bdbStorePath, true);
-            }
             super.tearDown();
         }
     }
 
     public void testCreateAndActivateVirtualHostNode() throws Exception
     {
+        String messageStorePath = _helper.getMessageStorePath();
         String repStreamTimeout = "2 h";
         String nodeName = "node";
         String groupName = "group";
@@ -146,11 +93,11 @@ public class BDBHAVirtualHostNodeTest ex
         attributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName);
         attributes.put(BDBHAVirtualHostNode.ADDRESS, nodeHostPort);
         attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperHostPort);
-        attributes.put(BDBHAVirtualHostNode.STORE_PATH, _bdbStorePath);
+        attributes.put(BDBHAVirtualHostNode.STORE_PATH, messageStorePath);
         attributes.put(BDBHAVirtualHostNode.CONTEXT,
                 Collections.singletonMap(ReplicationConfig.REP_STREAM_TIMEOUT, repStreamTimeout));
 
-        BDBHAVirtualHostNode<?> node = createHaVHN(attributes);
+        BDBHAVirtualHostNode<?> node = _helper.createHaVHN(attributes);
 
         final CountDownLatch virtualHostAddedLatch = new CountDownLatch(1);
         node.addChangeListener(new NoopConfigurationChangeListener()
@@ -167,7 +114,7 @@ public class BDBHAVirtualHostNodeTest ex
         });
 
         node.start();
-        assertNodeRole(node, "MASTER", "REPLICA");
+        _helper.assertNodeRole(node, "MASTER", "REPLICA");
         assertEquals("Unexpected node state", State.ACTIVE, node.getState());
 
         DurableConfigurationStore store = node.getConfigurationStore();
@@ -201,7 +148,7 @@ public class BDBHAVirtualHostNodeTest ex
         node.delete();
         assertEquals("Unexpected state returned after delete", State.DELETED, node.getState());
         assertEquals("Unexpected state", State.DELETED, node.getState());
-        assertFalse("Store still exists " + _bdbStorePath, _bdbStorePath.exists());
+        assertFalse("Store still exists " + messageStorePath, new File(messageStorePath).exists());
     }
 
     public void testMutableAttributes() throws Exception
@@ -216,9 +163,9 @@ public class BDBHAVirtualHostNodeTest ex
         attributes.put(BDBHAVirtualHostNode.GROUP_NAME, "group");
         attributes.put(BDBHAVirtualHostNode.ADDRESS, address);
         attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, address);
-        attributes.put(BDBHAVirtualHostNode.STORE_PATH, _bdbStorePath);
+        attributes.put(BDBHAVirtualHostNode.STORE_PATH, _helper.getMessageStorePath());
 
-        BDBHAVirtualHostNode<?> node = createAndStartHaVHN(attributes);
+        BDBHAVirtualHostNode<?> node = _helper.createAndStartHaVHN(attributes);
 
         BDBConfigurationStore bdbConfigurationStore = (BDBConfigurationStore) node.getConfigurationStore();
         ReplicatedEnvironment environment = (ReplicatedEnvironment) bdbConfigurationStore.getEnvironmentFacade().getEnvironment();
@@ -241,6 +188,7 @@ public class BDBHAVirtualHostNodeTest ex
 
     public void testTransferMasterToSelf() throws Exception
     {
+        String messageStorePath = _helper.getMessageStorePath();
         int node1PortNumber = findFreePort();
         String helperAddress = "localhost:" + node1PortNumber;
         String groupName = "group";
@@ -252,8 +200,8 @@ public class BDBHAVirtualHostNodeTest ex
         node1Attributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName);
         node1Attributes.put(BDBHAVirtualHostNode.ADDRESS, helperAddress);
         node1Attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress);
-        node1Attributes.put(BDBHAVirtualHostNode.STORE_PATH, _bdbStorePath + File.separator + "1");
-        createAndStartHaVHN(node1Attributes);
+        node1Attributes.put(BDBHAVirtualHostNode.STORE_PATH, messageStorePath + File.separator + "1");
+        _helper.createAndStartHaVHN(node1Attributes);
 
         int node2PortNumber = getNextAvailable(node1PortNumber+1);
 
@@ -264,8 +212,8 @@ public class BDBHAVirtualHostNodeTest ex
         node2Attributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName);
         node2Attributes.put(BDBHAVirtualHostNode.ADDRESS, "localhost:" + node2PortNumber);
         node2Attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress);
-        node2Attributes.put(BDBHAVirtualHostNode.STORE_PATH, _bdbStorePath + File.separator + "2");
-        createAndStartHaVHN(node2Attributes);
+        node2Attributes.put(BDBHAVirtualHostNode.STORE_PATH, messageStorePath + File.separator + "2");
+        _helper.createAndStartHaVHN(node2Attributes);
 
         int node3PortNumber = getNextAvailable(node2PortNumber+1);
         Map<String, Object> node3Attributes = new HashMap<String, Object>();
@@ -275,14 +223,14 @@ public class BDBHAVirtualHostNodeTest ex
         node3Attributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName);
         node3Attributes.put(BDBHAVirtualHostNode.ADDRESS, "localhost:" + node3PortNumber);
         node3Attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress);
-        node3Attributes.put(BDBHAVirtualHostNode.STORE_PATH, _bdbStorePath + File.separator + "3");
-        createAndStartHaVHN(node3Attributes);
+        node3Attributes.put(BDBHAVirtualHostNode.STORE_PATH, messageStorePath + File.separator + "3");
+        _helper.createAndStartHaVHN(node3Attributes);
 
-        BDBHAVirtualHostNode<?> replica = awaitAndFindNodeInRole("REPLICA");
+        BDBHAVirtualHostNode<?> replica = _helper.awaitAndFindNodeInRole("REPLICA");
 
         replica.setAttribute(BDBHAVirtualHostNode.ROLE, "REPLICA", "MASTER");
 
-        assertNodeRole(replica, "MASTER");
+        _helper.assertNodeRole(replica, "MASTER");
     }
 
     public void testTransferMasterToRemoteReplica() throws Exception
@@ -290,6 +238,7 @@ public class BDBHAVirtualHostNodeTest ex
         int node1PortNumber = findFreePort();
         String helperAddress = "localhost:" + node1PortNumber;
         String groupName = "group";
+        String messageStorePath = _helper.getMessageStorePath();
 
         Map<String, Object> node1Attributes = new HashMap<String, Object>();
         node1Attributes.put(BDBHAVirtualHostNode.ID, UUID.randomUUID());
@@ -298,9 +247,9 @@ public class BDBHAVirtualHostNodeTest ex
         node1Attributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName);
         node1Attributes.put(BDBHAVirtualHostNode.ADDRESS, helperAddress);
         node1Attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress);
-        node1Attributes.put(BDBHAVirtualHostNode.STORE_PATH, _bdbStorePath + File.separator + "1");
+        node1Attributes.put(BDBHAVirtualHostNode.STORE_PATH, messageStorePath + File.separator + "1");
 
-        BDBHAVirtualHostNode<?> node1 = createAndStartHaVHN(node1Attributes);
+        BDBHAVirtualHostNode<?> node1 = _helper.createAndStartHaVHN(node1Attributes);
 
         final AtomicReference<RemoteReplicationNode<?>> lastSeenReplica = new AtomicReference<>();
         final CountDownLatch remoteNodeLatch = new CountDownLatch(2);
@@ -326,9 +275,9 @@ public class BDBHAVirtualHostNodeTest ex
         node2Attributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName);
         node2Attributes.put(BDBHAVirtualHostNode.ADDRESS, "localhost:" + node2PortNumber);
         node2Attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress);
-        node2Attributes.put(BDBHAVirtualHostNode.STORE_PATH, _bdbStorePath + File.separator + "2");
+        node2Attributes.put(BDBHAVirtualHostNode.STORE_PATH, messageStorePath + File.separator + "2");
 
-        BDBHAVirtualHostNode<?> node2 = createAndStartHaVHN(node2Attributes);
+        BDBHAVirtualHostNode<?> node2 = _helper.createAndStartHaVHN(node2Attributes);
 
         int node3PortNumber = getNextAvailable(node2PortNumber+1);
         Map<String, Object> node3Attributes = new HashMap<String, Object>();
@@ -338,18 +287,18 @@ public class BDBHAVirtualHostNodeTest ex
         node3Attributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName);
         node3Attributes.put(BDBHAVirtualHostNode.ADDRESS, "localhost:" + node3PortNumber);
         node3Attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress);
-        node3Attributes.put(BDBHAVirtualHostNode.STORE_PATH, _bdbStorePath + File.separator + "3");
-        BDBHAVirtualHostNode<?> node3 = createAndStartHaVHN(node3Attributes);
+        node3Attributes.put(BDBHAVirtualHostNode.STORE_PATH, messageStorePath + File.separator + "3");
+        BDBHAVirtualHostNode<?> node3 = _helper.createAndStartHaVHN(node3Attributes);
 
         assertTrue("Replication nodes have not been seen during 5s", remoteNodeLatch.await(5, TimeUnit.SECONDS));
 
         BDBHARemoteReplicationNodeImpl replicaRemoteNode = (BDBHARemoteReplicationNodeImpl)lastSeenReplica.get();
-        awaitForAttributeChange(replicaRemoteNode, BDBHARemoteReplicationNodeImpl.ROLE, "REPLICA");
+        _helper.awaitForAttributeChange(replicaRemoteNode, BDBHARemoteReplicationNodeImpl.ROLE, "REPLICA");
 
         replicaRemoteNode.setAttributes(Collections.<String,Object>singletonMap(BDBHARemoteReplicationNode.ROLE, "MASTER"));
 
         BDBHAVirtualHostNode<?> replica = replicaRemoteNode.getName().equals(node2.getName())? node2 : node3;
-        assertNodeRole(replica, "MASTER");
+        _helper.assertNodeRole(replica, "MASTER");
     }
 
     public void testMutatingRoleWhenNotReplica_IsDisallowed() throws Exception
@@ -357,6 +306,7 @@ public class BDBHAVirtualHostNodeTest ex
         int nodePortNumber = findFreePort();
         String helperAddress = "localhost:" + nodePortNumber;
         String groupName = "group";
+        String messageStorePath = _helper.getMessageStorePath();
 
         Map<String, Object> node1Attributes = new HashMap<String, Object>();
         node1Attributes.put(BDBHAVirtualHostNode.ID, UUID.randomUUID());
@@ -365,10 +315,10 @@ public class BDBHAVirtualHostNodeTest ex
         node1Attributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName);
         node1Attributes.put(BDBHAVirtualHostNode.ADDRESS, helperAddress);
         node1Attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress);
-        node1Attributes.put(BDBHAVirtualHostNode.STORE_PATH, _bdbStorePath + File.separator + "1");
+        node1Attributes.put(BDBHAVirtualHostNode.STORE_PATH, messageStorePath + File.separator + "1");
 
-        BDBHAVirtualHostNode<?> node = createAndStartHaVHN(node1Attributes);
-        assertNodeRole(node, "MASTER");
+        BDBHAVirtualHostNode<?> node = _helper.createAndStartHaVHN(node1Attributes);
+        _helper.assertNodeRole(node, "MASTER");
 
         try
         {
@@ -384,6 +334,7 @@ public class BDBHAVirtualHostNodeTest ex
 
     public void testRemoveReplicaNode() throws Exception
     {
+        String messageStorePath = _helper.getMessageStorePath();
         int node1PortNumber = findFreePort();
         String helperAddress = "localhost:" + node1PortNumber;
         String groupName = "group";
@@ -395,8 +346,8 @@ public class BDBHAVirtualHostNodeTest ex
         node1Attributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName);
         node1Attributes.put(BDBHAVirtualHostNode.ADDRESS, helperAddress);
         node1Attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress);
-        node1Attributes.put(BDBHAVirtualHostNode.STORE_PATH, _bdbStorePath + File.separator + "1");
-        createAndStartHaVHN(node1Attributes);
+        node1Attributes.put(BDBHAVirtualHostNode.STORE_PATH, messageStorePath + File.separator + "1");
+        _helper.createAndStartHaVHN(node1Attributes);
 
         int node2PortNumber = getNextAvailable(node1PortNumber+1);
 
@@ -407,8 +358,8 @@ public class BDBHAVirtualHostNodeTest ex
         node2Attributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName);
         node2Attributes.put(BDBHAVirtualHostNode.ADDRESS, "localhost:" + node2PortNumber);
         node2Attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress);
-        node2Attributes.put(BDBHAVirtualHostNode.STORE_PATH, _bdbStorePath + File.separator + "2");
-        createAndStartHaVHN(node2Attributes);
+        node2Attributes.put(BDBHAVirtualHostNode.STORE_PATH, messageStorePath + File.separator + "2");
+        _helper.createAndStartHaVHN(node2Attributes);
 
         int node3PortNumber = getNextAvailable(node2PortNumber+1);
         Map<String, Object> node3Attributes = new HashMap<String, Object>();
@@ -418,20 +369,20 @@ public class BDBHAVirtualHostNodeTest ex
         node3Attributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName);
         node3Attributes.put(BDBHAVirtualHostNode.ADDRESS, "localhost:" + node3PortNumber);
         node3Attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress);
-        node3Attributes.put(BDBHAVirtualHostNode.STORE_PATH, _bdbStorePath + File.separator + "3");
-        createAndStartHaVHN(node3Attributes);
+        node3Attributes.put(BDBHAVirtualHostNode.STORE_PATH, messageStorePath + File.separator + "3");
+        _helper.createAndStartHaVHN(node3Attributes);
 
-        BDBHAVirtualHostNode<?> master = awaitAndFindNodeInRole("MASTER");
-        awaitRemoteNodes(master, 2);
+        BDBHAVirtualHostNode<?> master = _helper.awaitAndFindNodeInRole("MASTER");
+        _helper.awaitRemoteNodes(master, 2);
 
-        BDBHAVirtualHostNode<?> replica = awaitAndFindNodeInRole("REPLICA");
+        BDBHAVirtualHostNode<?> replica = _helper.awaitAndFindNodeInRole("REPLICA");
 
-        assertNotNull("Remote node " + replica.getName() + " is not found", findRemoteNode( master, replica.getName()));
+        assertNotNull("Remote node " + replica.getName() + " is not found", _helper.findRemoteNode(master, replica.getName()));
         replica.delete();
 
-        awaitRemoteNodes(master, 1);
+        _helper.awaitRemoteNodes(master, 1);
 
-        assertNull("Remote node " + replica.getName() + " is not found", findRemoteNode( master, replica.getName()));
+        assertNull("Remote node " + replica.getName() + " is not found", _helper.findRemoteNode(master, replica.getName()));
     }
 
 
@@ -448,8 +399,8 @@ public class BDBHAVirtualHostNodeTest ex
         nodeAttributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName);
         nodeAttributes.put(BDBHAVirtualHostNode.ADDRESS, helperAddress);
         nodeAttributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress);
-        nodeAttributes.put(BDBHAVirtualHostNode.STORE_PATH, _bdbStorePath + File.separator + "1");
-        BDBHAVirtualHostNode<?> node = createHaVHN(nodeAttributes);
+        nodeAttributes.put(BDBHAVirtualHostNode.STORE_PATH, _helper.getMessageStorePath() + File.separator + "1");
+        BDBHAVirtualHostNode<?> node = _helper.createHaVHN(nodeAttributes);
 
         final CountDownLatch virtualHostAddedLatch = new CountDownLatch(1);
         node.addChangeListener(new NoopConfigurationChangeListener()
@@ -466,14 +417,14 @@ public class BDBHAVirtualHostNodeTest ex
         });
 
         node.start();
-        assertNodeRole(node, "MASTER", "REPLICA");
+        _helper.assertNodeRole(node, "MASTER", "REPLICA");
         assertEquals("Unexpected node state", State.ACTIVE, node.getState());
 
         assertTrue("Virtual host child has not been added", virtualHostAddedLatch.await(30, TimeUnit.SECONDS));
         BDBHAVirtualHostImpl virtualHost = (BDBHAVirtualHostImpl)node.getVirtualHost();
         assertNotNull("Virtual host is not created", virtualHost);
 
-        awaitForAttributeChange(virtualHost, BDBHAVirtualHostImpl.COALESCING_SYNC, true);
+        _helper.awaitForAttributeChange(virtualHost, BDBHAVirtualHostImpl.COALESCING_SYNC, true);
 
         assertEquals("Unexpected local transaction synchronization policy", "SYNC", virtualHost.getLocalTransactionSynchronizationPolicy());
         assertEquals("Unexpected remote transaction synchronization policy", "NO_SYNC", virtualHost.getRemoteTransactionSynchronizationPolicy());
@@ -514,6 +465,7 @@ public class BDBHAVirtualHostNodeTest ex
 
     public void testIntruderProtection() throws Exception
     {
+        String messageStorePath = _helper.getMessageStorePath();
         int node1PortNumber = findFreePort();
         String helperAddress = "localhost:" + node1PortNumber;
         String groupName = "group";
@@ -525,9 +477,9 @@ public class BDBHAVirtualHostNodeTest ex
         node1Attributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName);
         node1Attributes.put(BDBHAVirtualHostNode.ADDRESS, helperAddress);
         node1Attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress);
-        node1Attributes.put(BDBHAVirtualHostNode.STORE_PATH, _bdbStorePath + File.separator + "1");
+        node1Attributes.put(BDBHAVirtualHostNode.STORE_PATH, messageStorePath + File.separator + "1");
 
-        BDBHAVirtualHostNode<?> node1 = createAndStartHaVHN(node1Attributes);
+        BDBHAVirtualHostNode<?> node1 = _helper.createAndStartHaVHN(node1Attributes);
         BDBHAVirtualHost<?> host = (BDBHAVirtualHost<?>)node1.getVirtualHost();
 
         List<String> permittedNodes = new ArrayList<String>();
@@ -543,11 +495,11 @@ public class BDBHAVirtualHostNodeTest ex
         node2Attributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName);
         node2Attributes.put(BDBHAVirtualHostNode.ADDRESS, "localhost:" + node2PortNumber);
         node2Attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress);
-        node2Attributes.put(BDBHAVirtualHostNode.STORE_PATH, _bdbStorePath + File.separator + "2");
+        node2Attributes.put(BDBHAVirtualHostNode.STORE_PATH, messageStorePath + File.separator + "2");
         node2Attributes.put(BDBHAVirtualHostNode.HELPER_NODE_NAME, "node1");
         node2Attributes.put(BDBHAVirtualHostNode.PRIORITY, 0);
 
-        BDBHAVirtualHostNode<?> node2 = createAndStartHaVHN(node2Attributes);
+        BDBHAVirtualHostNode<?> node2 = _helper.createAndStartHaVHN(node2Attributes);
 
         int node3PortNumber = getNextAvailable(node2PortNumber+1);
         Map<String, Object> node3Attributes = new HashMap<String, Object>();
@@ -557,13 +509,13 @@ public class BDBHAVirtualHostNodeTest ex
         node3Attributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName);
         node3Attributes.put(BDBHAVirtualHostNode.ADDRESS, "localhost:" + node3PortNumber);
         node3Attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress);
-        node3Attributes.put(BDBHAVirtualHostNode.STORE_PATH, _bdbStorePath + File.separator + "3");
+        node3Attributes.put(BDBHAVirtualHostNode.STORE_PATH, messageStorePath + File.separator + "3");
         node3Attributes.put(BDBHAVirtualHostNode.HELPER_NODE_NAME, "node1");
         node3Attributes.put(BDBHAVirtualHostNode.PRIORITY, 0);
 
         try
         {
-            createHaVHN(node3Attributes);
+            _helper.createHaVHN(node3Attributes);
             fail("The VHN should not be permitted to join the group");
         }
         catch(IllegalConfigurationException e)
@@ -588,13 +540,14 @@ public class BDBHAVirtualHostNodeTest ex
         };
         node1.addChangeListener(listener);
 
-        createHaVHN(node3Attributes);
+        _helper.createHaVHN(node3Attributes);
 
         assertTrue("Intruder protection was not triggered during expected timeout", stopLatch.await(10, TimeUnit.SECONDS));
     }
 
     public void testIntruderProtectionInManagementMode() throws Exception
     {
+        String messageStorePath = _helper.getMessageStorePath();
         int node1PortNumber = findFreePort();
         String helperAddress = "localhost:" + node1PortNumber;
         String groupName = "group";
@@ -606,9 +559,9 @@ public class BDBHAVirtualHostNodeTest ex
         node1Attributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName);
         node1Attributes.put(BDBHAVirtualHostNode.ADDRESS, helperAddress);
         node1Attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress);
-        node1Attributes.put(BDBHAVirtualHostNode.STORE_PATH, _bdbStorePath + File.separator + "1");
+        node1Attributes.put(BDBHAVirtualHostNode.STORE_PATH, messageStorePath + File.separator + "1");
 
-        BDBHAVirtualHostNode<?> node1 = createAndStartHaVHN(node1Attributes);
+        BDBHAVirtualHostNode<?> node1 = _helper.createAndStartHaVHN(node1Attributes);
 
         int node2PortNumber = getNextAvailable(node1PortNumber+1);
         Map<String, Object> node2Attributes = new HashMap<String, Object>();
@@ -618,11 +571,11 @@ public class BDBHAVirtualHostNodeTest ex
         node2Attributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName);
         node2Attributes.put(BDBHAVirtualHostNode.ADDRESS, "localhost:" + node2PortNumber);
         node2Attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress);
-        node2Attributes.put(BDBHAVirtualHostNode.STORE_PATH, _bdbStorePath + File.separator + "2");
+        node2Attributes.put(BDBHAVirtualHostNode.STORE_PATH, messageStorePath + File.separator + "2");
         node2Attributes.put(BDBHAVirtualHostNode.HELPER_NODE_NAME, "node1");
         node2Attributes.put(BDBHAVirtualHostNode.PRIORITY, 0);
 
-        BDBHAVirtualHostNode<?> node2 = createAndStartHaVHN(node2Attributes);
+        BDBHAVirtualHostNode<?> node2 = _helper.createAndStartHaVHN(node2Attributes);
 
         final CountDownLatch stopLatch = new CountDownLatch(1);
         ConfigurationChangeListener listener = new NoopConfigurationChangeListener()
@@ -646,17 +599,18 @@ public class BDBHAVirtualHostNodeTest ex
 
         assertTrue("Intruder protection was not triggered during expected timeout", stopLatch.await(10, TimeUnit.SECONDS));
 
-        when(_broker.isManagementMode()).thenReturn(true);
+        when(_helper.getBroker().isManagementMode()).thenReturn(true);
         node1.start();
 
-        awaitRemoteNodes(node1, 1);
+        _helper.awaitRemoteNodes(node1, 1);
 
-        BDBHARemoteReplicationNode<?> remote = findRemoteNode(node1, node2.getName());
+        BDBHARemoteReplicationNode<?> remote = _helper.findRemoteNode(node1, node2.getName());
         remote.delete();
     }
 
     public void testIntruderConnectedBeforePermittedNodesAreSet() throws Exception
     {
+        String messageStorePath = _helper.getMessageStorePath();
         int node1PortNumber = findFreePort();
         String helperAddress = "localhost:" + node1PortNumber;
         String groupName = "group";
@@ -668,9 +622,9 @@ public class BDBHAVirtualHostNodeTest ex
         node1Attributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName);
         node1Attributes.put(BDBHAVirtualHostNode.ADDRESS, helperAddress);
         node1Attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress);
-        node1Attributes.put(BDBHAVirtualHostNode.STORE_PATH, _bdbStorePath + File.separator + "1");
+        node1Attributes.put(BDBHAVirtualHostNode.STORE_PATH, messageStorePath + File.separator + "1");
 
-        BDBHAVirtualHostNode<?> node1 = createAndStartHaVHN(node1Attributes);
+        BDBHAVirtualHostNode<?> node1 = _helper.createAndStartHaVHN(node1Attributes);
 
         int node2PortNumber = getNextAvailable(node1PortNumber+1);
         Map<String, Object> node2Attributes = new HashMap<String, Object>();
@@ -680,10 +634,10 @@ public class BDBHAVirtualHostNodeTest ex
         node2Attributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName);
         node2Attributes.put(BDBHAVirtualHostNode.ADDRESS, "localhost:" + node2PortNumber);
         node2Attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress);
-        node2Attributes.put(BDBHAVirtualHostNode.STORE_PATH, _bdbStorePath + File.separator + "2");
+        node2Attributes.put(BDBHAVirtualHostNode.STORE_PATH, messageStorePath + File.separator + "2");
         node2Attributes.put(BDBHAVirtualHostNode.HELPER_NODE_NAME, "node1");
 
-        createAndStartHaVHN(node2Attributes);
+        _helper.createAndStartHaVHN(node2Attributes);
 
         final CountDownLatch stopLatch = new CountDownLatch(1);
         ConfigurationChangeListener listener = new NoopConfigurationChangeListener()
@@ -707,145 +661,6 @@ public class BDBHAVirtualHostNodeTest ex
         assertTrue("Intruder protection was not triggered during expected timeout", stopLatch.await(20, TimeUnit.SECONDS));
     }
 
-    private BDBHARemoteReplicationNode<?> findRemoteNode(BDBHAVirtualHostNode<?> node, String name)
-    {
-        for (RemoteReplicationNode<?> remoteNode : node.getRemoteReplicationNodes())
-        {
-            if (remoteNode.getName().equals(name))
-            {
-                return (BDBHARemoteReplicationNode<?>)remoteNode;
-            }
-        }
-        return null;
-    }
-
-    private void awaitRemoteNodes(BDBHAVirtualHostNode<?> node, int expectedNodeNumber) throws InterruptedException
-    {
-        int counter = 0;
-
-        @SuppressWarnings("rawtypes")
-        Collection<? extends RemoteReplicationNode> remoteNodes = null;
-        do
-        {
-            remoteNodes = node.getRemoteReplicationNodes();
-            if (counter > 0)
-            {
-                Thread.sleep(100);
-            }
-            counter++;
-        }
-        while(remoteNodes.size() != expectedNodeNumber && counter<100);
-        assertEquals("Unexpected node number", expectedNodeNumber, node.getRemoteReplicationNodes().size());
-    }
-
-    private void awaitForAttributeChange(ConfiguredObject<?> object, String name, Object expectedValue) throws InterruptedException
-    {
-        int awaitCounter = 0;
-        while(!object.equals(object.getAttribute(name)) && awaitCounter < 50)
-        {
-            Thread.sleep(100);
-            awaitCounter++;
-        }
-        assertEquals("Unexpected attribute " + name + " on " + object, expectedValue, object.getAttribute(name) );
-    }
-
-    private BDBHAVirtualHostNode<?> awaitAndFindNodeInRole(String role) throws InterruptedException
-    {
-        BDBHAVirtualHostNode<?> replica = null;
-        int findReplicaCount = 0;
-        while(replica == null)
-        {
-            replica = findNodeInRole(role);
-            if (replica == null)
-            {
-                Thread.sleep(100);
-            }
-            if (findReplicaCount > 50)
-            {
-                fail("Could not find a node in replica role");
-            }
-            findReplicaCount++;
-        }
-        return replica;
-    }
-
-    private BDBHAVirtualHostNode<?> findNodeInRole(String role)
-    {
-        for (BDBHAVirtualHostNode<?> node : _nodes)
-        {
-            if (role.equals(node.getRole()))
-            {
-                return node;
-            }
-        }
-        return null;
-    }
-
-    private BDBHAVirtualHostNode<?> createHaVHN(Map<String, Object> attributes)
-    {
-        @SuppressWarnings("unchecked")
-        BDBHAVirtualHostNode<?> node = (BDBHAVirtualHostNode<?>) _objectFactory.create(VirtualHostNode.class, attributes, _broker);
-        _nodes.add(node);
-        return node;
-    }
-
-    private void assertNodeRole(BDBHAVirtualHostNode<?> node, String... roleName) throws InterruptedException
-    {
-        int iterationCounter = 0;
-        boolean inRole =false;
-        do
-        {
-            for (String role : roleName)
-            {
-                if (role.equals(node.getRole()))
-                {
-                    inRole = true;
-                    break;
-                }
-            }
-            if (!inRole)
-            {
-                Thread.sleep(100);
-            }
-            iterationCounter++;
-        }
-        while(!inRole && iterationCounter<50);
-        assertTrue("Node " + node.getName() + " did not transit into role " + Arrays.toString(roleName), inRole);
-    }
-
-    private BDBHAVirtualHostNode<?> createAndStartHaVHN(Map<String, Object> attributes)  throws InterruptedException
-    {
-        BDBHAVirtualHostNode<?> node = createHaVHN(attributes);
-        node.start();
-        assertNodeRole(node, "MASTER", "REPLICA");
-        assertEquals("Unexpected node state", State.ACTIVE, node.getState());
-        return node;
-    }
-
-    class NoopConfigurationChangeListener implements ConfigurationChangeListener
-    {
-
-        @Override
-        public void stateChanged(ConfiguredObject<?> object, State oldState, State newState)
-        {
-        }
-
-        @Override
-        public void childAdded(ConfiguredObject<?> object, ConfiguredObject<?> child)
-        {
-        }
-
-        @Override
-        public void childRemoved(ConfiguredObject<?> object, ConfiguredObject<?> child)
-        {
-        }
-
-        @Override
-        public void attributeSet(ConfiguredObject<?> object, String attributeName, Object oldAttributeValue,
-                Object newAttributeValue)
-        {
-        }
-    }
 }
 
 

Added: qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/NoopConfigurationChangeListener.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/NoopConfigurationChangeListener.java?rev=1610379&view=auto
==============================================================================
--- qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/NoopConfigurationChangeListener.java (added)
+++ qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/NoopConfigurationChangeListener.java Mon Jul 14 10:26:17 2014
@@ -0,0 +1,53 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.server.store.berkeleydb;
+
+import org.apache.qpid.server.model.ConfigurationChangeListener;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.State;
+
+public class NoopConfigurationChangeListener implements ConfigurationChangeListener
+{
+
+    public NoopConfigurationChangeListener() {
+    }
+
+    @Override
+    public void stateChanged(ConfiguredObject<?> object, State oldState, State newState)
+    {
+    }
+
+    @Override
+    public void childAdded(ConfiguredObject<?> object, ConfiguredObject<?> child)
+    {
+    }
+
+    @Override
+    public void childRemoved(ConfiguredObject<?> object, ConfiguredObject<?> child)
+    {
+    }
+
+    @Override
+    public void attributeSet(ConfiguredObject<?> object, String attributeName, Object oldAttributeValue,
+                             Object newAttributeValue)
+    {
+    }
+}

Modified: qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacadeTest.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacadeTest.java?rev=1610379&r1=1610378&r2=1610379&view=diff
==============================================================================
--- qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacadeTest.java (original)
+++ qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacadeTest.java Mon Jul 14 10:26:17 2014
@@ -862,5 +862,10 @@ public class ReplicatedEnvironmentFacade
             LOGGER.warn("Intruder node " + node);
         }
 
+        @Override
+        public void onNoMajority()
+        {
+        }
+
     }
 }

Added: qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeOperationalLoggingTest.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeOperationalLoggingTest.java?rev=1610379&view=auto
==============================================================================
--- qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeOperationalLoggingTest.java (added)
+++ qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeOperationalLoggingTest.java Mon Jul 14 10:26:17 2014
@@ -0,0 +1,309 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.server.virtualhostnode.berkeleydb;
+
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.qpid.server.logging.EventLogger;
+import org.apache.qpid.server.logging.LogMessage;
+import org.apache.qpid.server.logging.messages.HighAvailabilityMessages;
+import org.apache.qpid.server.model.SystemContext;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.mockito.ArgumentMatcher;
+
+/**
+ * Class to test that specific VHN operations result in the expected Operational Log message(s) being performed.
+ */
+public class BDBHAVirtualHostNodeOperationalLoggingTest extends QpidTestCase
+{
+    private BDBHAVirtualHostNodeTestHelper _helper;
+    private EventLogger _eventLogger;
+
+    @Override
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+        _helper = new BDBHAVirtualHostNodeTestHelper(getTestName());
+        _eventLogger = mock(EventLogger.class);
+        SystemContext<?> context = (SystemContext<?>) _helper.getBroker().getParent(SystemContext.class);
+        when(context.getEventLogger()).thenReturn(_eventLogger);
+    }
+
+    @Override
+    protected void tearDown() throws Exception
+    {
+        try
+        {
+            _helper.tearDown();
+        }
+        finally
+        {
+            super.tearDown();
+        }
+    }
+
+    public void testCreate() throws Exception
+    {
+        int node1PortNumber = findFreePort();
+        String helperAddress = "localhost:" + node1PortNumber;
+        String groupName = "group";
+        String nodeName = "node1";
+
+        Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress);
+        BDBHAVirtualHostNodeImpl node1 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node1Attributes);
+
+        _helper.assertNodeRole(node1, "MASTER");
+
+        String expectedMessage = HighAvailabilityMessages.ADDED(node1.getName(), node1.getGroupName()).toString();
+        verify(_eventLogger).message(eq(node1.getVirtualHostNodeLogSubject()),
+                argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.ADDED_LOG_HIERARCHY)));
+
+        expectedMessage = HighAvailabilityMessages.ATTACHED(node1.getName(), node1.getGroupName(), "UNKNOWN").toString();
+        verify(_eventLogger).message(eq(node1.getVirtualHostNodeLogSubject()),
+                argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.ATTACHED_LOG_HIERARCHY)));
+
+
+        expectedMessage = HighAvailabilityMessages.STARTED(node1.getName(), node1.getGroupName()).toString();
+        verify(_eventLogger).message(eq(node1.getVirtualHostNodeLogSubject()),
+                argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.STARTED_LOG_HIERARCHY)));
+
+        expectedMessage = HighAvailabilityMessages.ROLE_CHANGED(node1.getName(), node1.getGroupName(), "UNKNOWN", "MASTER").toString();
+        verify(_eventLogger).message(eq(node1.getVirtualHostNodeLogSubject()),
+                argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.ROLE_CHANGED_LOG_HIERARCHY)));
+    }
+
+    public void testStop() throws Exception
+    {
+        int node1PortNumber = findFreePort();
+        String helperAddress = "localhost:" + node1PortNumber;
+        String groupName = "group";
+        String nodeName = "node1";
+
+        Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress);
+        BDBHAVirtualHostNodeImpl node1 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node1Attributes);
+        _helper.assertNodeRole(node1, "MASTER");
+        reset(_eventLogger);
+
+        node1.stop();
+
+        String expectedMessage = HighAvailabilityMessages.DETACHED(node1.getName(), node1.getGroupName()).toString();
+        verify(_eventLogger).message(eq(node1.getVirtualHostNodeLogSubject()),
+                argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.DETACHED_LOG_HIERARCHY)));
+
+        expectedMessage = HighAvailabilityMessages.STOPPED(node1.getName(), node1.getGroupName()).toString();
+        verify(_eventLogger).message(eq(node1.getVirtualHostNodeLogSubject()),
+                argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.STOPPED_LOG_HIERARCHY)));
+    }
+
+    public void testClose() throws Exception
+    {
+        int node1PortNumber = findFreePort();
+        String helperAddress = "localhost:" + node1PortNumber;
+        String groupName = "group";
+        String nodeName = "node1";
+
+        Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress);
+        BDBHAVirtualHostNodeImpl node1 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node1Attributes);
+        _helper.assertNodeRole(node1, "MASTER");
+
+        reset(_eventLogger);
+
+        node1.close();
+
+        String expectedMessage = HighAvailabilityMessages.DETACHED(node1.getName(), node1.getGroupName()).toString();
+        verify(_eventLogger).message(eq(node1.getVirtualHostNodeLogSubject()),
+                argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.DETACHED_LOG_HIERARCHY)));
+    }
+
+    public void testDelete() throws Exception
+    {
+        int node1PortNumber = findFreePort();
+        String helperAddress = "localhost:" + node1PortNumber;
+        String groupName = "group";
+        String nodeName = "node1";
+
+        Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress);
+        BDBHAVirtualHostNodeImpl node1 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node1Attributes);
+        _helper.assertNodeRole(node1, "MASTER");
+
+        reset(_eventLogger);
+
+        node1.delete();
+
+        String expectedMessage = HighAvailabilityMessages.DETACHED(node1.getName(), node1.getGroupName()).toString();
+        verify(_eventLogger).message(eq(node1.getVirtualHostNodeLogSubject()),
+                argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.DETACHED_LOG_HIERARCHY)));
+
+        expectedMessage = HighAvailabilityMessages.DELETED(node1.getName(), node1.getGroupName()).toString();
+        verify(_eventLogger).message(eq(node1.getVirtualHostNodeLogSubject()),
+                argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.DELETED_LOG_HIERARCHY)));
+    }
+
+    public void testSetPriority() throws Exception
+    {
+        int node1PortNumber = findFreePort();
+        String helperAddress = "localhost:" + node1PortNumber;
+        String groupName = "group";
+        String nodeName = "node1";
+
+        Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress);
+        BDBHAVirtualHostNodeImpl node1 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node1Attributes);
+        _helper.assertNodeRole(node1, "MASTER");
+
+        reset(_eventLogger);
+
+        node1.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.PRIORITY, 10));
+
+        String expectedMessage = HighAvailabilityMessages.PRIORITY_CHANGED(node1.getName(), node1.getGroupName(), "10").toString();
+        verify(_eventLogger).message(eq(node1.getVirtualHostNodeLogSubject()),
+                argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.PRIORITY_CHANGED_LOG_HIERARCHY)));
+    }
+
+    public void testSetQuorumOverride() throws Exception
+    {
+        int node1PortNumber = findFreePort();
+        String helperAddress = "localhost:" + node1PortNumber;
+        String groupName = "group";
+        String nodeName = "node1";
+
+        Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress);
+        BDBHAVirtualHostNodeImpl node1 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node1Attributes);
+        _helper.assertNodeRole(node1, "MASTER");
+
+        reset(_eventLogger);
+
+        node1.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.QUORUM_OVERRIDE, 1));
+
+        String expectedMessage = HighAvailabilityMessages.QUORUM_OVERRIDE_CHANGED(node1.getName(), node1.getGroupName(), "1").toString();
+        verify(_eventLogger).message(eq(node1.getVirtualHostNodeLogSubject()),
+                argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.QUORUM_OVERRIDE_CHANGED_LOG_HIERARCHY)));
+    }
+
+    public void testSetDesignatedPrimary() throws Exception
+    {
+        int node1PortNumber = findFreePort();
+        String helperAddress = "localhost:" + node1PortNumber;
+        String groupName = "group";
+        String nodeName = "node1";
+
+        Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress);
+        BDBHAVirtualHostNodeImpl node1 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node1Attributes);
+        _helper.assertNodeRole(node1, "MASTER");
+
+        reset(_eventLogger);
+
+        node1.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.DESIGNATED_PRIMARY, true));
+
+        String expectedMessage = HighAvailabilityMessages.DESIGNATED_PRIMARY_CHANGED(node1.getName(), node1.getGroupName(), "true").toString();
+        verify(_eventLogger).message(eq(node1.getVirtualHostNodeLogSubject()),
+                argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.DESIGNATED_PRIMARY_CHANGED_LOG_HIERARCHY)));
+    }
+
+    public void testRemoteNodeAdded() throws Exception
+    {
+        int node1PortNumber = findFreePort();
+        String helperAddress = "localhost:" + node1PortNumber;
+        String groupName = "group";
+        String nodeName = "node1";
+
+        Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress);
+        BDBHAVirtualHostNodeImpl node1 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node1Attributes);
+        _helper.assertNodeRole(node1, "MASTER");
+
+        reset(_eventLogger);
+
+        resetEventLogger();
+
+        int node2PortNumber = getNextAvailable(node1PortNumber + 1);
+        Map<String, Object> node2Attributes = _helper.createNodeAttributes("node2", groupName, "localhost:" + node2PortNumber, helperAddress);
+        BDBHAVirtualHostNodeImpl node2 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node2Attributes);
+        _helper.awaitRemoteNodes(node1, 1);
+
+        String expectedMessage = HighAvailabilityMessages.ADDED(node2.getName(), groupName).toString();
+        verify(_eventLogger).message(eq(node1.getVirtualHostNodeLogSubject()),
+                argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.ADDED_LOG_HIERARCHY)));
+    }
+
+    public void testRemoteNodeRemoved() throws Exception
+    {
+        int node1PortNumber = findFreePort();
+        String helperAddress = "localhost:" + node1PortNumber;
+        String groupName = "group";
+        String nodeName = "node1";
+
+        Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress);
+        node1Attributes.put(BDBHAVirtualHostNode.DESIGNATED_PRIMARY, true);
+        BDBHAVirtualHostNodeImpl node1 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node1Attributes);
+        _helper.assertNodeRole(node1, "MASTER");
+
+        resetEventLogger();
+
+        int node2PortNumber = getNextAvailable(node1PortNumber + 1);
+        Map<String, Object> node2Attributes = _helper.createNodeAttributes("node2", groupName, "localhost:" + node2PortNumber, helperAddress);
+        BDBHAVirtualHostNodeImpl node2 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node2Attributes);
+        _helper.awaitRemoteNodes(node1, 1);
+
+        reset(_eventLogger);
+
+        node2.delete();
+        _helper.awaitRemoteNodes(node1, 0);
+
+        String expectedMessage = HighAvailabilityMessages.DELETED(node2.getName(), groupName).toString();
+        verify(_eventLogger).message(eq(node1.getVirtualHostNodeLogSubject()),
+                argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.DELETED_LOG_HIERARCHY)));
+    }
+
+    private EventLogger resetEventLogger()
+    {
+        EventLogger eventLogger = mock(EventLogger.class);
+        SystemContext<?> context = (SystemContext<?>) _helper.getBroker().getParent(SystemContext.class);
+        when(context.getEventLogger()).thenReturn(eventLogger);
+        return eventLogger;
+    }
+
+    class LogMessageMatcher extends ArgumentMatcher<LogMessage>
+    {
+
+        private String _expectedMessage;
+        private String _expectedHierarchy;
+
+        public LogMessageMatcher(String expectedMessage, String expectedHierarchy)
+        {
+            _expectedMessage = expectedMessage;
+            _expectedHierarchy = expectedHierarchy;
+        }
+
+        @Override
+        public boolean matches(Object argument)
+        {
+            LogMessage logMessage = (LogMessage)argument;
+            return _expectedMessage.equals( logMessage.toString()) && _expectedHierarchy.equals(logMessage.getLogHierarchy());
+        }
+    }
+}

Added: qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java?rev=1610379&view=auto
==============================================================================
--- qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java (added)
+++ qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java Mon Jul 14 10:26:17 2014
@@ -0,0 +1,264 @@
+/*
+ *
+ * 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.
+ *
+ */
+package org.apache.qpid.server.virtualhostnode.berkeleydb;
+
+import static org.mockito.Mockito.when;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import com.sleepycat.je.rep.ReplicationConfig;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.configuration.updater.TaskExecutorImpl;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObjectFactory;
+import org.apache.qpid.server.model.RemoteReplicationNode;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHostNode;
+import org.apache.qpid.server.util.BrokerTestHelper;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.util.FileUtils;
+
+/**
+ * Helper class to make the tests of BDB HA Virtual Host Nodes simpler and more concise.
+ */
+public class BDBHAVirtualHostNodeTestHelper
+{
+    private final String _testName;
+    private Broker<?> _broker;
+    private File _bdbStorePath;
+    private TaskExecutor _taskExecutor;
+    private final ConfiguredObjectFactory _objectFactory = BrokerModel.getInstance().getObjectFactory();
+    private final Set<BDBHAVirtualHostNode<?>> _nodes = new HashSet<>();
+
+    public BDBHAVirtualHostNodeTestHelper(String testName) throws Exception
+    {
+        _testName = testName;
+        _broker = BrokerTestHelper.createBrokerMock();
+
+        _taskExecutor = new TaskExecutorImpl();
+        _taskExecutor.start();
+        when(_broker.getTaskExecutor()).thenReturn(_taskExecutor);
+
+        _bdbStorePath = new File(QpidTestCase.TMP_FOLDER, _testName + "." + System.currentTimeMillis());
+        _bdbStorePath.deleteOnExit();
+    }
+
+    public void tearDown() throws Exception
+    {
+        try
+        {
+            Exception firstException = null;
+            for (VirtualHostNode<?> node : _nodes)
+            {
+                try
+                {
+                    node.delete();
+                }
+                catch(Exception e)
+                {
+                    if (firstException != null)
+                    {
+                        firstException = e;
+                    }
+                }
+                if (firstException != null)
+                {
+                    throw firstException;
+                }
+            }
+        }
+        finally
+        {
+            if (_taskExecutor != null)
+            {
+                _taskExecutor.stopImmediately();
+            }
+            if (_bdbStorePath != null)
+            {
+                FileUtils.delete(_bdbStorePath, true);
+            }
+        }
+    }
+
+    public BDBHARemoteReplicationNode<?> findRemoteNode(BDBHAVirtualHostNode<?> node, String name)
+    {
+        for (RemoteReplicationNode<?> remoteNode : node.getRemoteReplicationNodes())
+        {
+            if (remoteNode.getName().equals(name))
+            {
+                return (BDBHARemoteReplicationNode<?>)remoteNode;
+            }
+        }
+        return null;
+    }
+
+    public void awaitRemoteNodes(BDBHAVirtualHostNode<?> node, int expectedNodeNumber) throws InterruptedException
+    {
+        int counter = 0;
+
+        @SuppressWarnings("rawtypes")
+        Collection<? extends RemoteReplicationNode> remoteNodes = null;
+        do
+        {
+            remoteNodes = node.getRemoteReplicationNodes();
+            if (counter > 0)
+            {
+                Thread.sleep(100);
+            }
+            counter++;
+        }
+        // TODO: 30 seconds is quite a lot to wait, we need to reduce this limit
+        while(remoteNodes.size() != expectedNodeNumber && counter<100);
+        assertEquals("Unexpected node number", expectedNodeNumber, node.getRemoteReplicationNodes().size());
+    }
+
+    public void awaitForAttributeChange(ConfiguredObject<?> object, String name, Object expectedValue) throws InterruptedException
+    {
+        int awaitCounter = 0;
+        while(!object.equals(object.getAttribute(name)) && awaitCounter < 50)
+        {
+            Thread.sleep(100);
+            awaitCounter++;
+        }
+        assertEquals("Unexpected attribute " + name + " on " + object, expectedValue, object.getAttribute(name) );
+    }
+
+    public BDBHAVirtualHostNode<?> awaitAndFindNodeInRole(String role) throws InterruptedException
+    {
+        BDBHAVirtualHostNode<?> replica = null;
+        int findReplicaCount = 0;
+        while(replica == null)
+        {
+            replica = findNodeInRole(role);
+            if (replica == null)
+            {
+                Thread.sleep(100);
+            }
+            if (findReplicaCount > 50)
+            {
+                fail("Could not find a node in replica role");
+            }
+            findReplicaCount++;
+        }
+        return replica;
+    }
+
+    public BDBHAVirtualHostNode<?> findNodeInRole(String role)
+    {
+        for (BDBHAVirtualHostNode<?> node : _nodes)
+        {
+            if (role.equals(node.getRole()))
+            {
+                return node;
+            }
+        }
+        return null;
+    }
+
+    public BDBHAVirtualHostNode<?> createHaVHN(Map<String, Object> attributes)
+    {
+        @SuppressWarnings("unchecked")
+        BDBHAVirtualHostNode<?> node = (BDBHAVirtualHostNode<?>) _objectFactory.create(VirtualHostNode.class, attributes, _broker);
+        _nodes.add(node);
+        return node;
+    }
+
+    public void assertNodeRole(BDBHAVirtualHostNode<?> node, String... roleName) throws InterruptedException
+    {
+        int iterationCounter = 0;
+        boolean inRole =false;
+        do
+        {
+            for (String role : roleName)
+            {
+                if (role.equals(node.getRole()))
+                {
+                    inRole = true;
+                    break;
+                }
+            }
+            if (!inRole)
+            {
+                Thread.sleep(50);
+            }
+            iterationCounter++;
+        }
+        while(!inRole && iterationCounter<100);
+        assertTrue("Node " + node.getName() + " did not transit into role " + Arrays.toString(roleName), inRole);
+    }
+
+    public BDBHAVirtualHostNode<?> createAndStartHaVHN(Map<String, Object> attributes)  throws InterruptedException
+    {
+        BDBHAVirtualHostNode<?> node = createHaVHN(attributes);
+        return startNodeAndWait(node);
+    }
+
+    public BDBHAVirtualHostNode<?> startNodeAndWait(BDBHAVirtualHostNode<?> node) throws InterruptedException
+    {
+        node.start();
+        assertNodeRole(node, "MASTER", "REPLICA");
+        assertEquals("Unexpected node state", State.ACTIVE, node.getState());
+        return node;
+    }
+
+    public String getMessageStorePath()
+    {
+        return _bdbStorePath.getAbsolutePath();
+    }
+
+    public Broker getBroker()
+    {
+        return _broker;
+    }
+
+    Map<String, Object> createNodeAttributes(String nodeName, String groupName, String address, String helperAddress)
+    {
+        Map<String, Object> node1Attributes = new HashMap<String, Object>();
+        node1Attributes.put(BDBHAVirtualHostNode.ID, UUID.randomUUID());
+        node1Attributes.put(BDBHAVirtualHostNode.TYPE, "BDB_HA");
+        node1Attributes.put(BDBHAVirtualHostNode.NAME, nodeName);
+        node1Attributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName);
+        node1Attributes.put(BDBHAVirtualHostNode.ADDRESS, address);
+        node1Attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress);
+        node1Attributes.put(BDBHAVirtualHostNode.STORE_PATH, getMessageStorePath() + File.separator + nodeName);
+
+        Map<String, String> repConfig = new HashMap<String, String>();
+        repConfig.put(ReplicationConfig.REPLICA_ACK_TIMEOUT, "2 s");
+        repConfig.put(ReplicationConfig.INSUFFICIENT_REPLICAS_TIMEOUT, "2 s");
+
+        node1Attributes.put(BDBHAVirtualHostNode.CONTEXT, repConfig);
+
+        return node1Attributes;
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org