diff options
182 files changed, 6793 insertions, 7012 deletions
diff --git a/qpid/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java b/qpid/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java index aa4ddd8181..f36c1ecc6f 100644 --- a/qpid/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java +++ b/qpid/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java @@ -36,19 +36,12 @@ import javax.management.openmbean.TabularDataSupport; import javax.management.openmbean.TabularType; import org.apache.log4j.Logger; -import org.apache.qpid.server.store.StoreException; import org.apache.qpid.server.jmx.AMQManagedObject; import org.apache.qpid.server.jmx.ManagedObject; -import org.apache.qpid.server.store.berkeleydb.BDBHAMessageStore; +import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacade; /** * Management mbean for BDB HA. - * <p> - * At runtime, the classloader loading this clas must have visibility of the other Qpid JMX classes. This is - * currently arranged through OSGI using the <b>fragment</b> feature so that this bundle shares the - * same classloader as broker-plugins-management-jmx. See the <b>Fragment-Host:</b> header within the MANIFEST.MF - * of this bundle. - * </p> */ public class BDBHAMessageStoreManagerMBean extends AMQManagedObject implements ManagedBDBHAMessageStore { @@ -63,7 +56,7 @@ public class BDBHAMessageStoreManagerMBean extends AMQManagedObject implements M try { GROUP_MEMBER_ATTRIBUTE_TYPES = new OpenType<?>[] {SimpleType.STRING, SimpleType.STRING}; - final String[] itemNames = new String[] {BDBHAMessageStore.GRP_MEM_COL_NODE_NAME, BDBHAMessageStore.GRP_MEM_COL_NODE_HOST_PORT}; + final String[] itemNames = new String[] {ReplicatedEnvironmentFacade.GRP_MEM_COL_NODE_NAME, ReplicatedEnvironmentFacade.GRP_MEM_COL_NODE_HOST_PORT}; final String[] itemDescriptions = new String[] {"Unique node name", "Node host / port "}; GROUP_MEMBER_ROW = new CompositeType("GroupMember", "Replication group member", itemNames, @@ -71,7 +64,7 @@ public class BDBHAMessageStoreManagerMBean extends AMQManagedObject implements M GROUP_MEMBER_ATTRIBUTE_TYPES ); GROUP_MEMBERS_TABLE = new TabularType("GroupMembers", "Replication group memebers", GROUP_MEMBER_ROW, - new String[] {BDBHAMessageStore.GRP_MEM_COL_NODE_NAME}); + new String[] {ReplicatedEnvironmentFacade.GRP_MEM_COL_NODE_NAME}); } catch (final OpenDataException ode) { @@ -79,44 +72,46 @@ public class BDBHAMessageStoreManagerMBean extends AMQManagedObject implements M } } - private final BDBHAMessageStore _store; + private final ReplicatedEnvironmentFacade _replicatedEnvironmentFacade; + private final String _objectName; - protected BDBHAMessageStoreManagerMBean(BDBHAMessageStore store, ManagedObject parent) throws JMException + protected BDBHAMessageStoreManagerMBean(String virtualHostName, ReplicatedEnvironmentFacade replicatedEnvironmentFacade, ManagedObject parent) throws JMException { super(ManagedBDBHAMessageStore.class, ManagedBDBHAMessageStore.TYPE, ((AMQManagedObject)parent).getRegistry()); - LOGGER.debug("Creating BDBHAMessageStoreManagerMBean"); - _store = store; + LOGGER.debug("Creating BDBHAMessageStoreManagerMBean for " + virtualHostName); + _replicatedEnvironmentFacade = replicatedEnvironmentFacade; + _objectName = ObjectName.quote(virtualHostName); register(); } @Override public String getObjectInstanceName() { - return ObjectName.quote(_store.getName()); + return _objectName; } @Override public String getGroupName() { - return _store.getGroupName(); + return _replicatedEnvironmentFacade.getGroupName(); } @Override public String getNodeName() { - return _store.getNodeName(); + return _replicatedEnvironmentFacade.getNodeName(); } @Override public String getNodeHostPort() { - return _store.getNodeHostPort(); + return _replicatedEnvironmentFacade.getHostPort(); } @Override public String getHelperHostPort() { - return _store.getHelperHostPort(); + return _replicatedEnvironmentFacade.getHelperHostPort(); } @Override @@ -124,7 +119,7 @@ public class BDBHAMessageStoreManagerMBean extends AMQManagedObject implements M { try { - return _store.getDurability(); + return _replicatedEnvironmentFacade.getDurability(); } catch (RuntimeException e) { @@ -137,7 +132,7 @@ public class BDBHAMessageStoreManagerMBean extends AMQManagedObject implements M @Override public boolean getCoalescingSync() throws IOException, JMException { - return _store.isCoalescingSync(); + return _replicatedEnvironmentFacade.isCoalescingSync(); } @Override @@ -145,7 +140,7 @@ public class BDBHAMessageStoreManagerMBean extends AMQManagedObject implements M { try { - return _store.getNodeState(); + return _replicatedEnvironmentFacade.getNodeState(); } catch (RuntimeException e) { @@ -159,7 +154,7 @@ public class BDBHAMessageStoreManagerMBean extends AMQManagedObject implements M { try { - return _store.isDesignatedPrimary(); + return _replicatedEnvironmentFacade.isDesignatedPrimary(); } catch (RuntimeException e) { @@ -172,7 +167,7 @@ public class BDBHAMessageStoreManagerMBean extends AMQManagedObject implements M public TabularData getAllNodesInGroup() throws IOException, JMException { final TabularDataSupport data = new TabularDataSupport(GROUP_MEMBERS_TABLE); - final List<Map<String, String>> members = _store.getGroupMembers(); + final List<Map<String, String>> members = _replicatedEnvironmentFacade.getGroupMembers(); for (Map<String, String> map : members) { @@ -187,9 +182,9 @@ public class BDBHAMessageStoreManagerMBean extends AMQManagedObject implements M { try { - _store.removeNodeFromGroup(nodeName); + _replicatedEnvironmentFacade.removeNodeFromGroup(nodeName); } - catch (StoreException e) + catch (RuntimeException e) { LOGGER.error("Failed to remove node " + nodeName + " from group", e); throw new JMException(e.getMessage()); @@ -201,11 +196,11 @@ public class BDBHAMessageStoreManagerMBean extends AMQManagedObject implements M { try { - _store.setDesignatedPrimary(primary); + _replicatedEnvironmentFacade.setDesignatedPrimary(primary); } - catch (StoreException e) + catch (RuntimeException e) { - LOGGER.error("Failed to set node " + _store.getNodeName() + " as designated primary", e); + LOGGER.error("Failed to set node " + _replicatedEnvironmentFacade.getNodeName() + " as designated primary", e); throw new JMException(e.getMessage()); } } @@ -215,9 +210,9 @@ public class BDBHAMessageStoreManagerMBean extends AMQManagedObject implements M { try { - _store.updateAddress(nodeName, newHostName, newPort); + _replicatedEnvironmentFacade.updateAddress(nodeName, newHostName, newPort); } - catch(StoreException e) + catch(RuntimeException e) { LOGGER.error("Failed to update address for node " + nodeName + " to " + newHostName + ":" + newPort, e); throw new JMException(e.getMessage()); diff --git a/qpid/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java b/qpid/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java index 0492350a25..24d7513c5f 100644 --- a/qpid/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java +++ b/qpid/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java @@ -28,11 +28,13 @@ import org.apache.qpid.server.jmx.MBeanProvider; import org.apache.qpid.server.jmx.ManagedObject; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.store.berkeleydb.BDBHAMessageStore; +import org.apache.qpid.server.store.berkeleydb.BDBHAVirtualHostFactory; +import org.apache.qpid.server.store.berkeleydb.BDBMessageStore; +import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacade; /** * This provide will create a {@link BDBHAMessageStoreManagerMBean} if the child is a virtual - * host and of type {@link BDBHAMessageStore#TYPE}. + * host and of type {@link ReplicatedEnvironmentFacade#TYPE}. * */ public class BDBHAMessageStoreManagerMBeanProvider implements MBeanProvider @@ -47,8 +49,7 @@ public class BDBHAMessageStoreManagerMBeanProvider implements MBeanProvider @Override public boolean isChildManageableByMBean(ConfiguredObject child) { - return (child instanceof VirtualHost - && BDBHAMessageStore.TYPE.equals(child.getAttribute(VirtualHost.STORE_TYPE))); + return (child instanceof VirtualHost && BDBHAVirtualHostFactory.TYPE.equals(child.getType())); } @Override @@ -56,14 +57,15 @@ public class BDBHAMessageStoreManagerMBeanProvider implements MBeanProvider { VirtualHost virtualHostChild = (VirtualHost) child; - BDBHAMessageStore messageStore = (BDBHAMessageStore) virtualHostChild.getMessageStore(); + BDBMessageStore messageStore = (BDBMessageStore) virtualHostChild.getMessageStore(); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Creating mBean for child " + child); } - return new BDBHAMessageStoreManagerMBean(messageStore, (ManagedObject) parent); + ReplicatedEnvironmentFacade replicatedEnvironmentFacade = (ReplicatedEnvironmentFacade)messageStore.getEnvironmentFacade(); + return new BDBHAMessageStoreManagerMBean(virtualHostChild.getName(), replicatedEnvironmentFacade, (ManagedObject) parent); } @Override diff --git a/qpid/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanTest.java b/qpid/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanTest.java index 0d963ebdae..fa16d1061a 100644 --- a/qpid/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanTest.java +++ b/qpid/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanTest.java @@ -37,10 +37,9 @@ import javax.management.openmbean.TabularData; import junit.framework.TestCase; -import org.apache.qpid.server.store.StoreException; import org.apache.qpid.server.jmx.AMQManagedObject; import org.apache.qpid.server.jmx.ManagedObjectRegistry; -import org.apache.qpid.server.store.berkeleydb.BDBHAMessageStore; +import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacade; public class BDBHAMessageStoreManagerMBeanTest extends TestCase { @@ -53,7 +52,7 @@ public class BDBHAMessageStoreManagerMBeanTest extends TestCase private static final String TEST_STORE_NAME = "testStoreName"; private static final boolean TEST_DESIGNATED_PRIMARY_FLAG = false; - private BDBHAMessageStore _store; + private ReplicatedEnvironmentFacade _replicatedEnvironmentFacade; private BDBHAMessageStoreManagerMBean _mBean; private AMQManagedObject _mBeanParent; @@ -62,10 +61,10 @@ public class BDBHAMessageStoreManagerMBeanTest extends TestCase { super.setUp(); - _store = mock(BDBHAMessageStore.class); + _replicatedEnvironmentFacade = mock(ReplicatedEnvironmentFacade.class); _mBeanParent = mock(AMQManagedObject.class); when(_mBeanParent.getRegistry()).thenReturn(mock(ManagedObjectRegistry.class)); - _mBean = new BDBHAMessageStoreManagerMBean(_store, _mBeanParent); + _mBean = new BDBHAMessageStoreManagerMBean(TEST_STORE_NAME, _replicatedEnvironmentFacade, _mBeanParent); } @Override @@ -76,64 +75,62 @@ public class BDBHAMessageStoreManagerMBeanTest extends TestCase public void testObjectName() throws Exception { - when(_store.getName()).thenReturn(TEST_STORE_NAME); - String expectedObjectName = "org.apache.qpid:type=BDBHAMessageStore,name=" + ObjectName.quote(TEST_STORE_NAME); assertEquals(expectedObjectName, _mBean.getObjectName().toString()); } public void testGroupName() throws Exception { - when(_store.getGroupName()).thenReturn(TEST_GROUP_NAME); + when(_replicatedEnvironmentFacade.getGroupName()).thenReturn(TEST_GROUP_NAME); assertEquals(TEST_GROUP_NAME, _mBean.getAttribute(ManagedBDBHAMessageStore.ATTR_GROUP_NAME)); } public void testNodeName() throws Exception { - when(_store.getNodeName()).thenReturn(TEST_NODE_NAME); + when(_replicatedEnvironmentFacade.getNodeName()).thenReturn(TEST_NODE_NAME); assertEquals(TEST_NODE_NAME, _mBean.getAttribute(ManagedBDBHAMessageStore.ATTR_NODE_NAME)); } public void testNodeHostPort() throws Exception { - when(_store.getNodeHostPort()).thenReturn(TEST_NODE_HOST_PORT); + when(_replicatedEnvironmentFacade.getHostPort()).thenReturn(TEST_NODE_HOST_PORT); assertEquals(TEST_NODE_HOST_PORT, _mBean.getAttribute(ManagedBDBHAMessageStore.ATTR_NODE_HOST_PORT)); } public void testHelperHostPort() throws Exception { - when(_store.getHelperHostPort()).thenReturn(TEST_HELPER_HOST_PORT); + when(_replicatedEnvironmentFacade.getHelperHostPort()).thenReturn(TEST_HELPER_HOST_PORT); assertEquals(TEST_HELPER_HOST_PORT, _mBean.getAttribute(ManagedBDBHAMessageStore.ATTR_HELPER_HOST_PORT)); } public void testDurability() throws Exception { - when(_store.getDurability()).thenReturn(TEST_DURABILITY); + when(_replicatedEnvironmentFacade.getDurability()).thenReturn(TEST_DURABILITY); assertEquals(TEST_DURABILITY, _mBean.getAttribute(ManagedBDBHAMessageStore.ATTR_DURABILITY)); } public void testCoalescingSync() throws Exception { - when(_store.isCoalescingSync()).thenReturn(true); + when(_replicatedEnvironmentFacade.isCoalescingSync()).thenReturn(true); assertEquals(true, _mBean.getAttribute(ManagedBDBHAMessageStore.ATTR_COALESCING_SYNC)); } public void testNodeState() throws Exception { - when(_store.getNodeState()).thenReturn(TEST_NODE_STATE); + when(_replicatedEnvironmentFacade.getNodeState()).thenReturn(TEST_NODE_STATE); assertEquals(TEST_NODE_STATE, _mBean.getAttribute(ManagedBDBHAMessageStore.ATTR_NODE_STATE)); } public void testDesignatedPrimaryFlag() throws Exception { - when(_store.isDesignatedPrimary()).thenReturn(TEST_DESIGNATED_PRIMARY_FLAG); + when(_replicatedEnvironmentFacade.isDesignatedPrimary()).thenReturn(TEST_DESIGNATED_PRIMARY_FLAG); assertEquals(TEST_DESIGNATED_PRIMARY_FLAG, _mBean.getAttribute(ManagedBDBHAMessageStore.ATTR_DESIGNATED_PRIMARY)); } @@ -141,29 +138,29 @@ public class BDBHAMessageStoreManagerMBeanTest extends TestCase public void testGroupMembersForGroupWithOneNode() throws Exception { List<Map<String, String>> members = Collections.singletonList(createTestNodeResult()); - when(_store.getGroupMembers()).thenReturn(members); + when(_replicatedEnvironmentFacade.getGroupMembers()).thenReturn(members); final TabularData resultsTable = _mBean.getAllNodesInGroup(); - assertTableHasHeadingsNamed(resultsTable, BDBHAMessageStore.GRP_MEM_COL_NODE_NAME, BDBHAMessageStore.GRP_MEM_COL_NODE_HOST_PORT); + assertTableHasHeadingsNamed(resultsTable, ReplicatedEnvironmentFacade.GRP_MEM_COL_NODE_NAME, ReplicatedEnvironmentFacade.GRP_MEM_COL_NODE_HOST_PORT); final int numberOfDataRows = resultsTable.size(); assertEquals("Unexpected number of data rows", 1 ,numberOfDataRows); final CompositeData row = (CompositeData) resultsTable.values().iterator().next(); - assertEquals(TEST_NODE_NAME, row.get(BDBHAMessageStore.GRP_MEM_COL_NODE_NAME)); - assertEquals(TEST_NODE_HOST_PORT, row.get(BDBHAMessageStore.GRP_MEM_COL_NODE_HOST_PORT)); + assertEquals(TEST_NODE_NAME, row.get(ReplicatedEnvironmentFacade.GRP_MEM_COL_NODE_NAME)); + assertEquals(TEST_NODE_HOST_PORT, row.get(ReplicatedEnvironmentFacade.GRP_MEM_COL_NODE_HOST_PORT)); } public void testRemoveNodeFromReplicationGroup() throws Exception { _mBean.removeNodeFromGroup(TEST_NODE_NAME); - verify(_store).removeNodeFromGroup(TEST_NODE_NAME); + verify(_replicatedEnvironmentFacade).removeNodeFromGroup(TEST_NODE_NAME); } public void testRemoveNodeFromReplicationGroupWithError() throws Exception { - doThrow(new StoreException("mocked exception")).when(_store).removeNodeFromGroup(TEST_NODE_NAME); + doThrow(new RuntimeException("mocked exception")).when(_replicatedEnvironmentFacade).removeNodeFromGroup(TEST_NODE_NAME); try { @@ -180,12 +177,12 @@ public class BDBHAMessageStoreManagerMBeanTest extends TestCase { _mBean.setDesignatedPrimary(true); - verify(_store).setDesignatedPrimary(true); + verify(_replicatedEnvironmentFacade).setDesignatedPrimary(true); } public void testSetAsDesignatedPrimaryWithError() throws Exception { - doThrow(new StoreException("mocked exception")).when(_store).setDesignatedPrimary(true); + doThrow(new RuntimeException("mocked exception")).when(_replicatedEnvironmentFacade).setDesignatedPrimary(true); try { @@ -205,7 +202,7 @@ public class BDBHAMessageStoreManagerMBeanTest extends TestCase _mBean.updateAddress(TEST_NODE_NAME, newHostName, newPort); - verify(_store).updateAddress(TEST_NODE_NAME, newHostName, newPort); + verify(_replicatedEnvironmentFacade).updateAddress(TEST_NODE_NAME, newHostName, newPort); } private void assertTableHasHeadingsNamed(final TabularData resultsTable, String... headingNames) @@ -220,8 +217,8 @@ public class BDBHAMessageStoreManagerMBeanTest extends TestCase private Map<String, String> createTestNodeResult() { Map<String, String> items = new HashMap<String, String>(); - items.put(BDBHAMessageStore.GRP_MEM_COL_NODE_NAME, TEST_NODE_NAME); - items.put(BDBHAMessageStore.GRP_MEM_COL_NODE_HOST_PORT, TEST_NODE_HOST_PORT); + items.put(ReplicatedEnvironmentFacade.GRP_MEM_COL_NODE_NAME, TEST_NODE_NAME); + items.put(ReplicatedEnvironmentFacade.GRP_MEM_COL_NODE_HOST_PORT, TEST_NODE_HOST_PORT); return items; } } diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java deleted file mode 100644 index 7d7ebd32fe..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java +++ /dev/null @@ -1,1862 +0,0 @@ -/* - * - * 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 com.sleepycat.bind.tuple.ByteBinding; -import com.sleepycat.bind.tuple.IntegerBinding; -import com.sleepycat.bind.tuple.LongBinding; -import com.sleepycat.je.*; -import com.sleepycat.je.Transaction; - -import java.io.File; -import java.lang.ref.SoftReference; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.log4j.Logger; -import org.apache.qpid.server.store.StoreException; -import org.apache.qpid.server.message.EnqueueableMessage; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.store.*; -import org.apache.qpid.server.store.MessageStoreRecoveryHandler.StoredMessageRecoveryHandler; -import org.apache.qpid.server.store.TransactionLogRecoveryHandler.QueueEntryRecoveryHandler; -import org.apache.qpid.server.store.berkeleydb.entry.PreparedTransaction; -import org.apache.qpid.server.store.berkeleydb.entry.QueueEntryKey; -import org.apache.qpid.server.store.berkeleydb.entry.Xid; -import org.apache.qpid.server.store.berkeleydb.tuple.ConfiguredObjectBinding; -import org.apache.qpid.server.store.berkeleydb.tuple.ContentBinding; -import org.apache.qpid.server.store.berkeleydb.tuple.MessageMetaDataBinding; -import org.apache.qpid.server.store.berkeleydb.tuple.PreparedTransactionBinding; -import org.apache.qpid.server.store.berkeleydb.tuple.QueueEntryBinding; -import org.apache.qpid.server.store.berkeleydb.tuple.UUIDTupleBinding; -import org.apache.qpid.server.store.berkeleydb.tuple.XidBinding; -import org.apache.qpid.server.store.berkeleydb.upgrade.Upgrader; -import org.apache.qpid.util.FileUtils; - -public abstract class AbstractBDBMessageStore implements MessageStore, DurableConfigurationStore -{ - private static final Logger LOGGER = Logger.getLogger(AbstractBDBMessageStore.class); - - private static final int LOCK_RETRY_ATTEMPTS = 5; - - public static final int VERSION = 7; - - private static final Map<String, String> ENVCONFIG_DEFAULTS = Collections.unmodifiableMap(new HashMap<String, String>() - {{ - put(EnvironmentConfig.LOCK_N_LOCK_TABLES, "7"); - put(EnvironmentConfig.STATS_COLLECT, "false"); // Turn off stats generation - feature introduced (and on by default) from BDB JE 5.0.84 - }}); - - private final AtomicBoolean _closed = new AtomicBoolean(false); - - private Environment _environment; - - private static String CONFIGURED_OBJECTS = "CONFIGURED_OBJECTS"; - private static String MESSAGEMETADATADB_NAME = "MESSAGE_METADATA"; - private static String MESSAGECONTENTDB_NAME = "MESSAGE_CONTENT"; - private static String DELIVERYDB_NAME = "QUEUE_ENTRIES"; - private static String BRIDGEDB_NAME = "BRIDGES"; - private static String LINKDB_NAME = "LINKS"; - private static String XIDDB_NAME = "XIDS"; - private static String CONFIG_VERSION_DB = "CONFIG_VERSION"; - - private Database _configuredObjectsDb; - private Database _configVersionDb; - private Database _messageMetaDataDb; - private Database _messageContentDb; - private Database _deliveryDb; - private Database _bridgeDb; - private Database _linkDb; - private Database _xidDb; - - /* ======= - * Schema: - * ======= - * - * Queue: - * name(AMQShortString) - name(AMQShortString), owner(AMQShortString), - * arguments(FieldTable encoded as binary), exclusive (boolean) - * - * Exchange: - * name(AMQShortString) - name(AMQShortString), typeName(AMQShortString), autodelete (boolean) - * - * Binding: - * exchangeName(AMQShortString), queueName(AMQShortString), routingKey(AMQShortString), - * arguments (FieldTable encoded as binary) - 0 (zero) - * - * QueueEntry: - * queueName(AMQShortString), messageId (long) - 0 (zero) - * - * Message (MetaData): - * messageId (long) - bodySize (integer), metaData (MessageMetaData encoded as binary) - * - * Message (Content): - * messageId (long), byteOffset (integer) - dataLength(integer), data(binary) - */ - - private final AtomicLong _messageId = new AtomicLong(0); - - protected final StateManager _stateManager; - - private MessageStoreRecoveryHandler _messageRecoveryHandler; - - private TransactionLogRecoveryHandler _tlogRecoveryHandler; - - private ConfigurationRecoveryHandler _configRecoveryHandler; - - private long _totalStoreSize; - private boolean _limitBusted; - private long _persistentSizeLowThreshold; - private long _persistentSizeHighThreshold; - - private final EventManager _eventManager = new EventManager(); - private String _storeLocation; - - private Map<String, String> _envConfigMap; - private VirtualHost _virtualHost; - - public AbstractBDBMessageStore() - { - _stateManager = new StateManager(_eventManager); - } - - @Override - public void addEventListener(EventListener eventListener, Event... events) - { - _eventManager.addEventListener(eventListener, events); - } - - public void configureConfigStore(VirtualHost virtualHost, ConfigurationRecoveryHandler recoveryHandler) - { - _stateManager.attainState(State.INITIALISING); - - _configRecoveryHandler = recoveryHandler; - _virtualHost = virtualHost; - } - - public void configureMessageStore(VirtualHost virtualHost, MessageStoreRecoveryHandler messageRecoveryHandler, - TransactionLogRecoveryHandler tlogRecoveryHandler) - { - if(_stateManager.isInState(State.INITIAL)) - { - // Is acting as a message store, but not a durable config store - _stateManager.attainState(State.INITIALISING); - } - - _messageRecoveryHandler = messageRecoveryHandler; - _tlogRecoveryHandler = tlogRecoveryHandler; - _virtualHost = virtualHost; - - completeInitialisation(); - } - - private void completeInitialisation() - { - configure(_virtualHost); - - _stateManager.attainState(State.INITIALISED); - } - - public synchronized void activate() - { - // check if acting as a durable config store, but not a message store - if(_stateManager.isInState(State.INITIALISING)) - { - completeInitialisation(); - } - _stateManager.attainState(State.ACTIVATING); - - if(_configRecoveryHandler != null) - { - recoverConfig(_configRecoveryHandler); - } - if(_messageRecoveryHandler != null) - { - recoverMessages(_messageRecoveryHandler); - } - if(_tlogRecoveryHandler != null) - { - recoverQueueEntries(_tlogRecoveryHandler); - } - - _stateManager.attainState(State.ACTIVE); - } - - public org.apache.qpid.server.store.Transaction newTransaction() - { - return new BDBTransaction(); - } - - /** - * Called after instantiation in order to configure the message store. - * - * - * - * @param virtualHost The virtual host using this store - * @return whether a new store environment was created or not (to indicate whether recovery is necessary) - * - * @throws Exception If any error occurs that means the store is unable to configure itself. - */ - public void configure(VirtualHost virtualHost) - { - configure(virtualHost, _messageRecoveryHandler != null); - } - - public void configure(VirtualHost virtualHost, boolean isMessageStore) - { - String name = virtualHost.getName(); - final String defaultPath = System.getProperty("QPID_WORK") + File.separator + "bdbstore" + File.separator + name; - - String storeLocation; - if(isMessageStore) - { - storeLocation = (String) virtualHost.getAttribute(VirtualHost.STORE_PATH); - if(storeLocation == null) - { - storeLocation = defaultPath; - } - } - else // we are acting only as the durable config store - { - storeLocation = (String) virtualHost.getAttribute(VirtualHost.CONFIG_STORE_PATH); - if(storeLocation == null) - { - storeLocation = defaultPath; - } - } - - Object overfullAttr = virtualHost.getAttribute(MessageStoreConstants.OVERFULL_SIZE_ATTRIBUTE); - Object underfullAttr = virtualHost.getAttribute(MessageStoreConstants.UNDERFULL_SIZE_ATTRIBUTE); - - _persistentSizeHighThreshold = overfullAttr == null ? -1l : - overfullAttr instanceof Number ? ((Number) overfullAttr).longValue() : Long.parseLong(overfullAttr.toString()); - _persistentSizeLowThreshold = underfullAttr == null ? _persistentSizeHighThreshold : - underfullAttr instanceof Number ? ((Number) underfullAttr).longValue() : Long.parseLong(underfullAttr.toString()); - - - if(_persistentSizeLowThreshold > _persistentSizeHighThreshold || _persistentSizeLowThreshold < 0l) - { - _persistentSizeLowThreshold = _persistentSizeHighThreshold; - } - - File environmentPath = new File(storeLocation); - if (!environmentPath.exists()) - { - if (!environmentPath.mkdirs()) - { - throw new IllegalArgumentException("Environment path " + environmentPath + " could not be read or created. " - + "Ensure the path is correct and that the permissions are correct."); - } - } - - _storeLocation = storeLocation; - - _envConfigMap = new HashMap<String, String>(); - _envConfigMap.putAll(ENVCONFIG_DEFAULTS); - - Object bdbEnvConfigAttr = virtualHost.getAttribute("bdbEnvironmentConfig"); - if(bdbEnvConfigAttr instanceof Map) - { - _envConfigMap.putAll((Map)bdbEnvConfigAttr); - } - - LOGGER.info("Configuring BDB message store"); - - setupStore(environmentPath, name); - } - - protected Map<String,String> getConfigMap(Map<String, String> defaultConfig, Configuration config, String prefix) throws ConfigurationException - { - final List<Object> argumentNames = config.getList(prefix + ".name"); - final List<Object> argumentValues = config.getList(prefix + ".value"); - final int initialSize = argumentNames.size() + defaultConfig.size(); - - final Map<String,String> attributes = new HashMap<String,String>(initialSize); - attributes.putAll(defaultConfig); - - for (int i = 0; i < argumentNames.size(); i++) - { - final String argName = argumentNames.get(i).toString(); - final String argValue = argumentValues.get(i).toString(); - - attributes.put(argName, argValue); - } - - return Collections.unmodifiableMap(attributes); - } - - @Override - public String getStoreLocation() - { - return _storeLocation; - } - - /** - * Move the store state from INITIAL to ACTIVE without actually recovering. - * - * This is required if you do not want to perform recovery of the store data - * - * @throws org.apache.qpid.server.store.StoreException if the store is not in the correct state - */ - void startWithNoRecover() throws StoreException - { - _stateManager.attainState(State.INITIALISING); - _stateManager.attainState(State.INITIALISED); - _stateManager.attainState(State.ACTIVATING); - _stateManager.attainState(State.ACTIVE); - } - - protected void setupStore(File storePath, String name) - { - _environment = createEnvironment(storePath); - - new Upgrader(_environment, name).upgradeIfNecessary(); - - openDatabases(); - - _totalStoreSize = getSizeOnDisk(); - } - - protected abstract Environment createEnvironment(File environmentPath) throws DatabaseException; - - public Environment getEnvironment() - { - return _environment; - } - - private void openDatabases() throws DatabaseException - { - DatabaseConfig dbConfig = new DatabaseConfig(); - dbConfig.setTransactional(true); - dbConfig.setAllowCreate(true); - - //This is required if we are wanting read only access. - dbConfig.setReadOnly(false); - - _configuredObjectsDb = openDatabase(CONFIGURED_OBJECTS, dbConfig); - _configVersionDb = openDatabase(CONFIG_VERSION_DB, dbConfig); - _messageMetaDataDb = openDatabase(MESSAGEMETADATADB_NAME, dbConfig); - _messageContentDb = openDatabase(MESSAGECONTENTDB_NAME, dbConfig); - _deliveryDb = openDatabase(DELIVERYDB_NAME, dbConfig); - _linkDb = openDatabase(LINKDB_NAME, dbConfig); - _bridgeDb = openDatabase(BRIDGEDB_NAME, dbConfig); - _xidDb = openDatabase(XIDDB_NAME, dbConfig); - } - - private Database openDatabase(final String dbName, final DatabaseConfig dbConfig) - { - // if opening read-only and the database doesn't exist, then you can't create it - return dbConfig.getReadOnly() && !_environment.getDatabaseNames().contains(dbName) - ? null - : _environment.openDatabase(null, dbName, dbConfig); - } - - /** - * Called to close and cleanup any resources used by the message store. - * - * @throws Exception If the close fails. - */ - public void close() - { - if (_closed.compareAndSet(false, true)) - { - _stateManager.attainState(State.CLOSING); - closeInternal(); - _stateManager.attainState(State.CLOSED); - } - } - - protected void closeInternal() - { - if (_messageMetaDataDb != null) - { - LOGGER.info("Closing message metadata database"); - _messageMetaDataDb.close(); - } - - if (_messageContentDb != null) - { - LOGGER.info("Closing message content database"); - _messageContentDb.close(); - } - - if (_configuredObjectsDb != null) - { - LOGGER.info("Closing configurable objects database"); - _configuredObjectsDb.close(); - } - - if (_deliveryDb != null) - { - LOGGER.info("Close delivery database"); - _deliveryDb.close(); - } - - if (_bridgeDb != null) - { - LOGGER.info("Close bridge database"); - _bridgeDb.close(); - } - - if (_linkDb != null) - { - LOGGER.info("Close link database"); - _linkDb.close(); - } - - - if (_xidDb != null) - { - LOGGER.info("Close xid database"); - _xidDb.close(); - } - - - if (_configVersionDb != null) - { - LOGGER.info("Close config version database"); - _configVersionDb.close(); - } - - closeEnvironment(); - - } - - private void closeEnvironment() throws DatabaseException - { - if (_environment != null) - { - // Clean the log before closing. This makes sure it doesn't contain - // redundant data. Closing without doing this means the cleaner may not - // get a chance to finish. - try - { - _environment.cleanLog(); - } - finally - { - _environment.close(); - } - } - } - - - private void recoverConfig(ConfigurationRecoveryHandler recoveryHandler) - { - try - { - final int configVersion = getConfigVersion(); - recoveryHandler.beginConfigurationRecovery(this, configVersion); - loadConfiguredObjects(recoveryHandler); - - final int newConfigVersion = recoveryHandler.completeConfigurationRecovery(); - if(newConfigVersion != configVersion) - { - updateConfigVersion(newConfigVersion); - } - } - catch (DatabaseException e) - { - throw new StoreException("Error recovering persistent state: " + e.getMessage(), e); - } - - } - - private void updateConfigVersion(int newConfigVersion) throws StoreException - { - Cursor cursor = null; - try - { - Transaction txn = _environment.beginTransaction(null, null); - cursor = _configVersionDb.openCursor(txn, null); - DatabaseEntry key = new DatabaseEntry(); - ByteBinding.byteToEntry((byte) 0,key); - DatabaseEntry value = new DatabaseEntry(); - - while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) - { - IntegerBinding.intToEntry(newConfigVersion, value); - OperationStatus status = cursor.put(key, value); - if (status != OperationStatus.SUCCESS) - { - throw new StoreException("Error setting config version: " + status); - } - } - cursor.close(); - cursor = null; - txn.commit(); - } - finally - { - closeCursorSafely(cursor); - } - - } - - private int getConfigVersion() throws StoreException - { - Cursor cursor = null; - try - { - cursor = _configVersionDb.openCursor(null, null); - DatabaseEntry key = new DatabaseEntry(); - DatabaseEntry value = new DatabaseEntry(); - while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) - { - return IntegerBinding.entryToInt(value); - } - - // Insert 0 as the default config version - IntegerBinding.intToEntry(0,value); - ByteBinding.byteToEntry((byte) 0,key); - OperationStatus status = _configVersionDb.put(null, key, value); - if (status != OperationStatus.SUCCESS) - { - throw new StoreException("Error initialising config version: " + status); - } - return 0; - } - finally - { - closeCursorSafely(cursor); - } - } - - private void loadConfiguredObjects(ConfigurationRecoveryHandler crh) throws DatabaseException - { - Cursor cursor = null; - try - { - cursor = _configuredObjectsDb.openCursor(null, null); - DatabaseEntry key = new DatabaseEntry(); - DatabaseEntry value = new DatabaseEntry(); - while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) - { - UUID id = UUIDTupleBinding.getInstance().entryToObject(key); - - ConfiguredObjectRecord configuredObject = new ConfiguredObjectBinding(id).entryToObject(value); - crh.configuredObject(configuredObject.getId(),configuredObject.getType(),configuredObject.getAttributes()); - } - - } - finally - { - closeCursorSafely(cursor); - } - } - - private void closeCursorSafely(Cursor cursor) - { - if (cursor != null) - { - cursor.close(); - } - } - - - private void recoverMessages(MessageStoreRecoveryHandler msrh) throws DatabaseException - { - StoredMessageRecoveryHandler mrh = msrh.begin(); - - Cursor cursor = null; - try - { - cursor = _messageMetaDataDb.openCursor(null, null); - DatabaseEntry key = new DatabaseEntry(); - DatabaseEntry value = new DatabaseEntry(); - MessageMetaDataBinding valueBinding = MessageMetaDataBinding.getInstance(); - - long maxId = 0; - - while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) - { - long messageId = LongBinding.entryToLong(key); - StorableMessageMetaData metaData = valueBinding.entryToObject(value); - - StoredBDBMessage message = new StoredBDBMessage(messageId, metaData, true); - - mrh.message(message); - - maxId = Math.max(maxId, messageId); - } - - _messageId.set(maxId); - } - catch (DatabaseException e) - { - LOGGER.error("Database Error: " + e.getMessage(), e); - throw e; - } - finally - { - closeCursorSafely(cursor); - } - } - - private void recoverQueueEntries(TransactionLogRecoveryHandler recoveryHandler) - throws DatabaseException - { - QueueEntryRecoveryHandler qerh = recoveryHandler.begin(this); - - ArrayList<QueueEntryKey> entries = new ArrayList<QueueEntryKey>(); - - Cursor cursor = null; - try - { - cursor = _deliveryDb.openCursor(null, null); - DatabaseEntry key = new DatabaseEntry(); - QueueEntryBinding keyBinding = QueueEntryBinding.getInstance(); - - DatabaseEntry value = new DatabaseEntry(); - while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) - { - QueueEntryKey qek = keyBinding.entryToObject(key); - - entries.add(qek); - } - - try - { - cursor.close(); - } - finally - { - cursor = null; - } - - for(QueueEntryKey entry : entries) - { - UUID queueId = entry.getQueueId(); - long messageId = entry.getMessageId(); - qerh.queueEntry(queueId, messageId); - } - } - catch (DatabaseException e) - { - LOGGER.error("Database Error: " + e.getMessage(), e); - throw e; - } - finally - { - closeCursorSafely(cursor); - } - - TransactionLogRecoveryHandler.DtxRecordRecoveryHandler dtxrh = qerh.completeQueueEntryRecovery(); - - cursor = null; - try - { - cursor = _xidDb.openCursor(null, null); - DatabaseEntry key = new DatabaseEntry(); - XidBinding keyBinding = XidBinding.getInstance(); - PreparedTransactionBinding valueBinding = new PreparedTransactionBinding(); - DatabaseEntry value = new DatabaseEntry(); - - while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) - { - Xid xid = keyBinding.entryToObject(key); - PreparedTransaction preparedTransaction = valueBinding.entryToObject(value); - dtxrh.dtxRecord(xid.getFormat(),xid.getGlobalId(),xid.getBranchId(), - preparedTransaction.getEnqueues(),preparedTransaction.getDequeues()); - } - - } - catch (DatabaseException e) - { - LOGGER.error("Database Error: " + e.getMessage(), e); - throw e; - } - finally - { - closeCursorSafely(cursor); - } - - - dtxrh.completeDtxRecordRecovery(); - } - - public void removeMessage(long messageId, boolean sync) throws StoreException - { - - boolean complete = false; - com.sleepycat.je.Transaction tx = null; - - Random rand = null; - int attempts = 0; - try - { - do - { - tx = null; - try - { - tx = _environment.beginTransaction(null, null); - - //remove the message meta data from the store - DatabaseEntry key = new DatabaseEntry(); - LongBinding.longToEntry(messageId, key); - - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Removing message id " + messageId); - } - - - OperationStatus status = _messageMetaDataDb.delete(tx, key); - if (status == OperationStatus.NOTFOUND) - { - LOGGER.info("Message not found (attempt to remove failed - probably application initiated rollback) " + - messageId); - } - - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Deleted metadata for message " + messageId); - } - - //now remove the content data from the store if there is any. - DatabaseEntry contentKeyEntry = new DatabaseEntry(); - LongBinding.longToEntry(messageId, contentKeyEntry); - _messageContentDb.delete(tx, contentKeyEntry); - - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Deleted content for message " + messageId); - } - - commit(tx, sync); - complete = true; - tx = null; - } - catch (LockConflictException e) - { - try - { - if(tx != null) - { - tx.abort(); - } - } - catch(DatabaseException e2) - { - LOGGER.warn("Unable to abort transaction after LockConflictExcption", e2); - // rethrow the original log conflict exception, the secondary exception should already have - // been logged. - throw e; - } - - - LOGGER.warn("Lock timeout exception. Retrying (attempt " - + (attempts+1) + " of "+ LOCK_RETRY_ATTEMPTS +") " + e); - - if(++attempts < LOCK_RETRY_ATTEMPTS) - { - if(rand == null) - { - rand = new Random(); - } - - try - { - Thread.sleep(500l + (long)(500l * rand.nextDouble())); - } - catch (InterruptedException e1) - { - - } - } - else - { - // rethrow the lock conflict exception since we could not solve by retrying - throw e; - } - } - } - while(!complete); - } - catch (DatabaseException e) - { - LOGGER.error("Unexpected BDB exception", e); - - if (tx != null) - { - try - { - tx.abort(); - tx = null; - } - catch (DatabaseException e1) - { - throw new StoreException("Error aborting transaction " + e1, e1); - } - } - - throw new StoreException("Error removing message with id " + messageId + " from database: " + e.getMessage(), e); - } - finally - { - if (tx != null) - { - try - { - tx.abort(); - tx = null; - } - catch (DatabaseException e1) - { - throw new StoreException("Error aborting transaction " + e1, e1); - } - } - } - } - - @Override - public void create(UUID id, String type, Map<String, Object> attributes) throws StoreException - { - if (_stateManager.isInState(State.ACTIVE)) - { - ConfiguredObjectRecord configuredObject = new ConfiguredObjectRecord(id, type, attributes); - storeConfiguredObjectEntry(configuredObject); - } - } - - @Override - public void remove(UUID id, String type) throws StoreException - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("public void remove(id = " + id + ", type="+type+"): called"); - } - OperationStatus status = removeConfiguredObject(null, id); - if (status == OperationStatus.NOTFOUND) - { - throw new StoreException("Configured object of type " + type + " with id " + id + " not found"); - } - } - - @Override - public UUID[] removeConfiguredObjects(final UUID... objects) throws StoreException - { - com.sleepycat.je.Transaction txn = _environment.beginTransaction(null, null); - Collection<UUID> removed = new ArrayList<UUID>(objects.length); - for(UUID id : objects) - { - if(removeConfiguredObject(txn, id) == OperationStatus.SUCCESS) - { - removed.add(id); - } - } - - txn.commit(); - return removed.toArray(new UUID[removed.size()]); - } - - @Override - public void update(UUID id, String type, Map<String, Object> attributes) throws StoreException - { - update(false, id, type, attributes, null); - } - - public void update(boolean createIfNecessary, ConfiguredObjectRecord... records) throws StoreException - { - com.sleepycat.je.Transaction txn = _environment.beginTransaction(null, null); - for(ConfiguredObjectRecord record : records) - { - update(createIfNecessary, record.getId(), record.getType(), record.getAttributes(), txn); - } - txn.commit(); - } - - private void update(boolean createIfNecessary, UUID id, String type, Map<String, Object> attributes, com.sleepycat.je.Transaction txn) throws - StoreException - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Updating " +type + ", id: " + id); - } - - try - { - DatabaseEntry key = new DatabaseEntry(); - UUIDTupleBinding keyBinding = UUIDTupleBinding.getInstance(); - keyBinding.objectToEntry(id, key); - - DatabaseEntry value = new DatabaseEntry(); - DatabaseEntry newValue = new DatabaseEntry(); - ConfiguredObjectBinding configuredObjectBinding = ConfiguredObjectBinding.getInstance(); - - OperationStatus status = _configuredObjectsDb.get(txn, key, value, LockMode.DEFAULT); - if (status == OperationStatus.SUCCESS || (createIfNecessary && status == OperationStatus.NOTFOUND)) - { - ConfiguredObjectRecord newQueueRecord = new ConfiguredObjectRecord(id, type, attributes); - - // write the updated entry to the store - configuredObjectBinding.objectToEntry(newQueueRecord, newValue); - status = _configuredObjectsDb.put(txn, key, newValue); - if (status != OperationStatus.SUCCESS) - { - throw new StoreException("Error updating queue details within the store: " + status); - } - } - else if (status != OperationStatus.NOTFOUND) - { - throw new StoreException("Error finding queue details within the store: " + status); - } - } - catch (DatabaseException e) - { - throw new StoreException("Error updating queue details within the store: " + e,e); - } - } - - /** - * Places a message onto a specified queue, in a given transaction. - * - * @param tx The transaction for the operation. - * @param queue The the queue to place the message on. - * @param messageId The message to enqueue. - * - * @throws org.apache.qpid.server.store.StoreException If the operation fails for any reason. - */ - public void enqueueMessage(final com.sleepycat.je.Transaction tx, final TransactionLogResource queue, - long messageId) throws StoreException - { - - DatabaseEntry key = new DatabaseEntry(); - QueueEntryBinding keyBinding = QueueEntryBinding.getInstance(); - QueueEntryKey dd = new QueueEntryKey(queue.getId(), messageId); - keyBinding.objectToEntry(dd, key); - DatabaseEntry value = new DatabaseEntry(); - ByteBinding.byteToEntry((byte) 0, value); - - try - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Enqueuing message " + messageId + " on queue " - + (queue instanceof AMQQueue ? ((AMQQueue) queue).getName() + " with id " : "") + queue.getId() - + " in transaction " + tx); - } - _deliveryDb.put(tx, key, value); - } - catch (DatabaseException e) - { - LOGGER.error("Failed to enqueue: " + e.getMessage(), e); - throw new StoreException("Error writing enqueued message with id " + messageId + " for queue " - + (queue instanceof AMQQueue ? ((AMQQueue) queue).getName() + " with id " : "") + queue.getId() - + " to database", e); - } - } - - /** - * Extracts a message from a specified queue, in a given transaction. - * - * @param tx The transaction for the operation. - * @param queue The queue to take the message from. - * @param messageId The message to dequeue. - * - * @throws org.apache.qpid.server.store.StoreException If the operation fails for any reason, or if the specified message does not exist. - */ - public void dequeueMessage(final com.sleepycat.je.Transaction tx, final TransactionLogResource queue, - long messageId) throws StoreException - { - - DatabaseEntry key = new DatabaseEntry(); - QueueEntryBinding keyBinding = QueueEntryBinding.getInstance(); - QueueEntryKey queueEntryKey = new QueueEntryKey(queue.getId(), messageId); - UUID id = queue.getId(); - keyBinding.objectToEntry(queueEntryKey, key); - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Dequeue message id " + messageId + " from queue " - + (queue instanceof AMQQueue ? ((AMQQueue) queue).getName() + " with id " : "") + id); - } - - try - { - - OperationStatus status = _deliveryDb.delete(tx, key); - if (status == OperationStatus.NOTFOUND) - { - throw new StoreException("Unable to find message with id " + messageId + " on queue " - + (queue instanceof AMQQueue ? ((AMQQueue) queue).getName() + " with id " : "") + id); - } - else if (status != OperationStatus.SUCCESS) - { - throw new StoreException("Unable to remove message with id " + messageId + " on queue" - + (queue instanceof AMQQueue ? ((AMQQueue) queue).getName() + " with id " : "") + id); - } - - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Removed message " + messageId + " on queue " - + (queue instanceof AMQQueue ? ((AMQQueue) queue).getName() + " with id " : "") + id - + " from delivery db"); - - } - } - catch (DatabaseException e) - { - - LOGGER.error("Failed to dequeue message " + messageId + ": " + e.getMessage(), e); - LOGGER.error(tx); - - throw new StoreException("Error accessing database while dequeuing message: " + e.getMessage(), e); - } - } - - - private void recordXid(com.sleepycat.je.Transaction txn, - long format, - byte[] globalId, - byte[] branchId, - org.apache.qpid.server.store.Transaction.Record[] enqueues, - org.apache.qpid.server.store.Transaction.Record[] dequeues) throws StoreException - { - DatabaseEntry key = new DatabaseEntry(); - Xid xid = new Xid(format, globalId, branchId); - XidBinding keyBinding = XidBinding.getInstance(); - keyBinding.objectToEntry(xid,key); - - DatabaseEntry value = new DatabaseEntry(); - PreparedTransaction preparedTransaction = new PreparedTransaction(enqueues, dequeues); - PreparedTransactionBinding valueBinding = new PreparedTransactionBinding(); - valueBinding.objectToEntry(preparedTransaction, value); - - try - { - _xidDb.put(txn, key, value); - } - catch (DatabaseException e) - { - LOGGER.error("Failed to write xid: " + e.getMessage(), e); - throw new StoreException("Error writing xid to database", e); - } - } - - private void removeXid(com.sleepycat.je.Transaction txn, long format, byte[] globalId, byte[] branchId) - throws StoreException - { - DatabaseEntry key = new DatabaseEntry(); - Xid xid = new Xid(format, globalId, branchId); - XidBinding keyBinding = XidBinding.getInstance(); - - keyBinding.objectToEntry(xid, key); - - - try - { - - OperationStatus status = _xidDb.delete(txn, key); - if (status == OperationStatus.NOTFOUND) - { - throw new StoreException("Unable to find xid"); - } - else if (status != OperationStatus.SUCCESS) - { - throw new StoreException("Unable to remove xid"); - } - - } - catch (DatabaseException e) - { - - LOGGER.error("Failed to remove xid ", e); - LOGGER.error(txn); - - throw new StoreException("Error accessing database while removing xid: " + e.getMessage(), e); - } - } - - /** - * Commits all operations performed within a given transaction. - * - * @param tx The transaction to commit all operations for. - * - * @throws org.apache.qpid.server.store.StoreException If the operation fails for any reason. - */ - private StoreFuture commitTranImpl(final com.sleepycat.je.Transaction tx, boolean syncCommit) throws - StoreException - { - if (tx == null) - { - throw new StoreException("Fatal internal error: transactional is null at commitTran"); - } - - StoreFuture result; - try - { - result = commit(tx, syncCommit); - - if (LOGGER.isDebugEnabled()) - { - String transactionType = syncCommit ? "synchronous" : "asynchronous"; - LOGGER.debug("commitTranImpl completed " + transactionType + " transaction " + tx); - } - } - catch (DatabaseException e) - { - throw new StoreException("Error commit tx: " + e.getMessage(), e); - } - - return result; - } - - /** - * Abandons all operations performed within a given transaction. - * - * @param tx The transaction to abandon. - * - * @throws org.apache.qpid.server.store.StoreException If the operation fails for any reason. - */ - public void abortTran(final com.sleepycat.je.Transaction tx) throws StoreException - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("abortTran called for transaction " + tx); - } - - try - { - tx.abort(); - } - catch (DatabaseException e) - { - throw new StoreException("Error aborting transaction: " + e.getMessage(), e); - } - } - - /** - * Primarily for testing purposes. - * - * @param queueId - * - * @return a list of message ids for messages enqueued for a particular queue - */ - List<Long> getEnqueuedMessages(UUID queueId) throws StoreException - { - Cursor cursor = null; - try - { - cursor = _deliveryDb.openCursor(null, null); - - DatabaseEntry key = new DatabaseEntry(); - - QueueEntryKey dd = new QueueEntryKey(queueId, 0); - - QueueEntryBinding keyBinding = QueueEntryBinding.getInstance(); - keyBinding.objectToEntry(dd, key); - - DatabaseEntry value = new DatabaseEntry(); - - LinkedList<Long> messageIds = new LinkedList<Long>(); - - OperationStatus status = cursor.getSearchKeyRange(key, value, LockMode.DEFAULT); - dd = keyBinding.entryToObject(key); - - while ((status == OperationStatus.SUCCESS) && dd.getQueueId().equals(queueId)) - { - - messageIds.add(dd.getMessageId()); - status = cursor.getNext(key, value, LockMode.DEFAULT); - if (status == OperationStatus.SUCCESS) - { - dd = keyBinding.entryToObject(key); - } - } - - return messageIds; - } - catch (DatabaseException e) - { - throw new StoreException("Database error: " + e.getMessage(), e); - } - finally - { - if (cursor != null) - { - try - { - cursor.close(); - } - catch (DatabaseException e) - { - throw new StoreException("Error closing cursor: " + e.getMessage(), e); - } - } - } - } - - /** - * Return a valid, currently unused message id. - * - * @return A fresh message id. - */ - public long getNewMessageId() - { - return _messageId.incrementAndGet(); - } - - /** - * Stores a chunk of message data. - * - * @param tx The transaction for the operation. - * @param messageId The message to store the data for. - * @param offset The offset of the data chunk in the message. - * @param contentBody The content of the data chunk. - * - * @throws org.apache.qpid.server.store.StoreException If the operation fails for any reason, or if the specified message does not exist. - */ - protected void addContent(final com.sleepycat.je.Transaction tx, long messageId, int offset, - ByteBuffer contentBody) throws StoreException - { - DatabaseEntry key = new DatabaseEntry(); - LongBinding.longToEntry(messageId, key); - DatabaseEntry value = new DatabaseEntry(); - ContentBinding messageBinding = ContentBinding.getInstance(); - messageBinding.objectToEntry(contentBody.array(), value); - try - { - OperationStatus status = _messageContentDb.put(tx, key, value); - if (status != OperationStatus.SUCCESS) - { - throw new StoreException("Error adding content for message id " + messageId + ": " + status); - } - - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Storing content for message " + messageId + " in transaction " + tx); - - } - } - catch (DatabaseException e) - { - throw new StoreException("Error writing AMQMessage with id " + messageId + " to database: " + e.getMessage(), e); - } - } - - /** - * Stores message meta-data. - * - * @param tx The transaction for the operation. - * @param messageId The message to store the data for. - * @param messageMetaData The message meta data to store. - * - * @throws org.apache.qpid.server.store.StoreException If the operation fails for any reason, or if the specified message does not exist. - */ - private void storeMetaData(final com.sleepycat.je.Transaction tx, long messageId, - StorableMessageMetaData messageMetaData) - throws StoreException - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("storeMetaData called for transaction " + tx - + ", messageId " + messageId - + ", messageMetaData " + messageMetaData); - } - - DatabaseEntry key = new DatabaseEntry(); - LongBinding.longToEntry(messageId, key); - DatabaseEntry value = new DatabaseEntry(); - - MessageMetaDataBinding messageBinding = MessageMetaDataBinding.getInstance(); - messageBinding.objectToEntry(messageMetaData, value); - try - { - _messageMetaDataDb.put(tx, key, value); - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Storing message metadata for message id " + messageId + " in transaction " + tx); - } - } - catch (DatabaseException e) - { - throw new StoreException("Error writing message metadata with id " + messageId + " to database: " + e.getMessage(), e); - } - } - - /** - * Retrieves message meta-data. - * - * @param messageId The message to get the meta-data for. - * - * @return The message meta data. - * - * @throws org.apache.qpid.server.store.StoreException If the operation fails for any reason, or if the specified message does not exist. - */ - public StorableMessageMetaData getMessageMetaData(long messageId) throws StoreException - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("public MessageMetaData getMessageMetaData(Long messageId = " - + messageId + "): called"); - } - - DatabaseEntry key = new DatabaseEntry(); - LongBinding.longToEntry(messageId, key); - DatabaseEntry value = new DatabaseEntry(); - MessageMetaDataBinding messageBinding = MessageMetaDataBinding.getInstance(); - - try - { - OperationStatus status = _messageMetaDataDb.get(null, key, value, LockMode.READ_UNCOMMITTED); - if (status != OperationStatus.SUCCESS) - { - throw new StoreException("Metadata not found for message with id " + messageId); - } - - StorableMessageMetaData mdd = messageBinding.entryToObject(value); - - return mdd; - } - catch (DatabaseException e) - { - throw new StoreException("Error reading message metadata for message with id " + messageId + ": " + e.getMessage(), e); - } - } - - /** - * Fills the provided ByteBuffer with as much content for the specified message as possible, starting - * from the specified offset in the message. - * - * @param messageId The message to get the data for. - * @param offset The offset of the data within the message. - * @param dst The destination of the content read back - * - * @return The number of bytes inserted into the destination - * - * @throws org.apache.qpid.server.store.StoreException If the operation fails for any reason, or if the specified message does not exist. - */ - public int getContent(long messageId, int offset, ByteBuffer dst) throws StoreException - { - DatabaseEntry contentKeyEntry = new DatabaseEntry(); - LongBinding.longToEntry(messageId, contentKeyEntry); - DatabaseEntry value = new DatabaseEntry(); - ContentBinding contentTupleBinding = ContentBinding.getInstance(); - - - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Message Id: " + messageId + " Getting content body from offset: " + offset); - } - - try - { - - int written = 0; - OperationStatus status = _messageContentDb.get(null, contentKeyEntry, value, LockMode.READ_UNCOMMITTED); - if (status == OperationStatus.SUCCESS) - { - byte[] dataAsBytes = contentTupleBinding.entryToObject(value); - int size = dataAsBytes.length; - if (offset > size) - { - throw new StoreException("Offset " + offset + " is greater than message size " + size - + " for message id " + messageId + "!"); - - } - - written = size - offset; - if(written > dst.remaining()) - { - written = dst.remaining(); - } - - dst.put(dataAsBytes, offset, written); - } - return written; - } - catch (DatabaseException e) - { - throw new StoreException("Error getting AMQMessage with id " + messageId + " to database: " + e.getMessage(), e); - } - } - - public boolean isPersistent() - { - return true; - } - - @SuppressWarnings("unchecked") - public <T extends StorableMessageMetaData> StoredMessage<T> addMessage(T metaData) - { - if(metaData.isPersistent()) - { - return (StoredMessage<T>) new StoredBDBMessage(getNewMessageId(), metaData); - } - else - { - return new StoredMemoryMessage(getNewMessageId(), metaData); - } - } - - //Package getters for the various databases used by the Store - - Database getMetaDataDb() - { - return _messageMetaDataDb; - } - - Database getContentDb() - { - return _messageContentDb; - } - - Database getDeliveryDb() - { - return _deliveryDb; - } - - /** - * Makes the specified configured object persistent. - * - * @param configuredObject Details of the configured object to store. - * @throws org.apache.qpid.server.store.StoreException If the operation fails for any reason. - */ - private void storeConfiguredObjectEntry(ConfiguredObjectRecord configuredObject) throws StoreException - { - if (_stateManager.isInState(State.ACTIVE)) - { - LOGGER.debug("Storing configured object: " + configuredObject); - DatabaseEntry key = new DatabaseEntry(); - UUIDTupleBinding keyBinding = UUIDTupleBinding.getInstance(); - keyBinding.objectToEntry(configuredObject.getId(), key); - - DatabaseEntry value = new DatabaseEntry(); - ConfiguredObjectBinding queueBinding = ConfiguredObjectBinding.getInstance(); - - queueBinding.objectToEntry(configuredObject, value); - try - { - OperationStatus status = _configuredObjectsDb.put(null, key, value); - if (status != OperationStatus.SUCCESS) - { - throw new StoreException("Error writing configured object " + configuredObject + " to database: " - + status); - } - } - catch (DatabaseException e) - { - throw new StoreException("Error writing configured object " + configuredObject - + " to database: " + e.getMessage(), e); - } - } - } - - private OperationStatus removeConfiguredObject(Transaction tx, UUID id) throws StoreException - { - - LOGGER.debug("Removing configured object: " + id); - DatabaseEntry key = new DatabaseEntry(); - UUIDTupleBinding uuidBinding = UUIDTupleBinding.getInstance(); - uuidBinding.objectToEntry(id, key); - try - { - return _configuredObjectsDb.delete(tx, key); - } - catch (DatabaseException e) - { - throw new StoreException("Error deleting of configured object with id " + id + " from database", e); - } - } - - protected abstract StoreFuture commit(com.sleepycat.je.Transaction tx, boolean syncCommit) throws DatabaseException; - - - private class StoredBDBMessage implements StoredMessage<StorableMessageMetaData> - { - - private final long _messageId; - private final boolean _isRecovered; - - private StorableMessageMetaData _metaData; - private volatile SoftReference<StorableMessageMetaData> _metaDataRef; - - private byte[] _data; - private volatile SoftReference<byte[]> _dataRef; - - StoredBDBMessage(long messageId, StorableMessageMetaData metaData) - { - this(messageId, metaData, false); - } - - StoredBDBMessage(long messageId, StorableMessageMetaData metaData, boolean isRecovered) - { - _messageId = messageId; - _isRecovered = isRecovered; - - if(!_isRecovered) - { - _metaData = metaData; - } - _metaDataRef = new SoftReference<StorableMessageMetaData>(metaData); - } - - public StorableMessageMetaData getMetaData() - { - StorableMessageMetaData metaData = _metaDataRef.get(); - if(metaData == null) - { - metaData = AbstractBDBMessageStore.this.getMessageMetaData(_messageId); - _metaDataRef = new SoftReference<StorableMessageMetaData>(metaData); - } - - return metaData; - } - - public long getMessageNumber() - { - return _messageId; - } - - public void addContent(int offsetInMessage, java.nio.ByteBuffer src) - { - src = src.slice(); - - if(_data == null) - { - _data = new byte[src.remaining()]; - _dataRef = new SoftReference<byte[]>(_data); - src.duplicate().get(_data); - } - else - { - byte[] oldData = _data; - _data = new byte[oldData.length + src.remaining()]; - _dataRef = new SoftReference<byte[]>(_data); - - System.arraycopy(oldData,0,_data,0,oldData.length); - src.duplicate().get(_data, oldData.length, src.remaining()); - } - - } - - public int getContent(int offsetInMessage, java.nio.ByteBuffer dst) - { - byte[] data = _dataRef == null ? null : _dataRef.get(); - if(data != null) - { - int length = Math.min(dst.remaining(), data.length - offsetInMessage); - dst.put(data, offsetInMessage, length); - return length; - } - else - { - return AbstractBDBMessageStore.this.getContent(_messageId, offsetInMessage, dst); - } - } - - public ByteBuffer getContent(int offsetInMessage, int size) - { - byte[] data = _dataRef == null ? null : _dataRef.get(); - if(data != null) - { - return ByteBuffer.wrap(data,offsetInMessage,size); - } - else - { - ByteBuffer buf = ByteBuffer.allocate(size); - int length = getContent(offsetInMessage, buf); - buf.limit(length); - buf.position(0); - return buf; - } - } - - synchronized void store(com.sleepycat.je.Transaction txn) - { - if (!stored()) - { - try - { - _dataRef = new SoftReference<byte[]>(_data); - AbstractBDBMessageStore.this.storeMetaData(txn, _messageId, _metaData); - AbstractBDBMessageStore.this.addContent(txn, _messageId, 0, - _data == null ? ByteBuffer.allocate(0) : ByteBuffer.wrap(_data)); - } - catch(DatabaseException e) - { - throw new StoreException(e); - } - finally - { - _metaData = null; - _data = null; - } - } - } - - public synchronized StoreFuture flushToStore() - { - if(!stored()) - { - com.sleepycat.je.Transaction txn = _environment.beginTransaction(null, null); - store(txn); - AbstractBDBMessageStore.this.commit(txn,true); - storedSizeChange(getMetaData().getContentSize()); - } - return StoreFuture.IMMEDIATE_FUTURE; - } - - public void remove() - { - int delta = getMetaData().getContentSize(); - AbstractBDBMessageStore.this.removeMessage(_messageId, false); - storedSizeChange(-delta); - } - - private boolean stored() - { - return _metaData == null || _isRecovered; - } - } - - private class BDBTransaction implements org.apache.qpid.server.store.Transaction - { - private com.sleepycat.je.Transaction _txn; - private int _storeSizeIncrease; - - private BDBTransaction() - { - try - { - _txn = _environment.beginTransaction(null, null); - } - catch (DatabaseException e) - { - LOGGER.error("Exception during transaction begin, closing store environment.", e); - closeEnvironmentSafely(); - - throw new StoreException("Exception during transaction begin, store environment closed.", e); - } - } - - public void enqueueMessage(TransactionLogResource queue, EnqueueableMessage message) - { - if(message.getStoredMessage() instanceof StoredBDBMessage) - { - final StoredBDBMessage storedMessage = (StoredBDBMessage) message.getStoredMessage(); - storedMessage.store(_txn); - _storeSizeIncrease += storedMessage.getMetaData().getContentSize(); - } - - AbstractBDBMessageStore.this.enqueueMessage(_txn, queue, message.getMessageNumber()); - } - - public void dequeueMessage(TransactionLogResource queue, EnqueueableMessage message) - { - AbstractBDBMessageStore.this.dequeueMessage(_txn, queue, message.getMessageNumber()); - } - - public void commitTran() - { - AbstractBDBMessageStore.this.commitTranImpl(_txn, true); - AbstractBDBMessageStore.this.storedSizeChange(_storeSizeIncrease); - } - - public StoreFuture commitTranAsync() - { - AbstractBDBMessageStore.this.storedSizeChange(_storeSizeIncrease); - return AbstractBDBMessageStore.this.commitTranImpl(_txn, false); - } - - public void abortTran() - { - AbstractBDBMessageStore.this.abortTran(_txn); - } - - public void removeXid(long format, byte[] globalId, byte[] branchId) - { - AbstractBDBMessageStore.this.removeXid(_txn, format, globalId, branchId); - - } - - public void recordXid(long format, byte[] globalId, byte[] branchId, Record[] enqueues, - Record[] dequeues) - { - AbstractBDBMessageStore.this.recordXid(_txn, format, globalId, branchId, enqueues, dequeues); - } - } - - private void storedSizeChange(final int delta) - { - if(getPersistentSizeHighThreshold() > 0) - { - synchronized (this) - { - // the delta supplied is an approximation of a store size change. we don;t want to check the statistic every - // time, so we do so only when there's been enough change that it is worth looking again. We do this by - // assuming the total size will change by less than twice the amount of the message data change. - long newSize = _totalStoreSize += 2*delta; - - if(!_limitBusted && newSize > getPersistentSizeHighThreshold()) - { - _totalStoreSize = getSizeOnDisk(); - - if(_totalStoreSize > getPersistentSizeHighThreshold()) - { - _limitBusted = true; - _eventManager.notifyEvent(Event.PERSISTENT_MESSAGE_SIZE_OVERFULL); - } - } - else if(_limitBusted && newSize < getPersistentSizeLowThreshold()) - { - long oldSize = _totalStoreSize; - _totalStoreSize = getSizeOnDisk(); - - if(oldSize <= _totalStoreSize) - { - - reduceSizeOnDisk(); - - _totalStoreSize = getSizeOnDisk(); - - } - - if(_totalStoreSize < getPersistentSizeLowThreshold()) - { - _limitBusted = false; - _eventManager.notifyEvent(Event.PERSISTENT_MESSAGE_SIZE_UNDERFULL); - } - - - } - } - } - } - - private void reduceSizeOnDisk() - { - _environment.getConfig().setConfigParam(EnvironmentConfig.ENV_RUN_CLEANER, "false"); - boolean cleaned = false; - while (_environment.cleanLog() > 0) - { - cleaned = true; - } - if (cleaned) - { - CheckpointConfig force = new CheckpointConfig(); - force.setForce(true); - _environment.checkpoint(force); - } - - - _environment.getConfig().setConfigParam(EnvironmentConfig.ENV_RUN_CLEANER, "true"); - } - - private long getSizeOnDisk() - { - return _environment.getStats(null).getTotalLogSize(); - } - - private long getPersistentSizeLowThreshold() - { - return _persistentSizeLowThreshold; - } - - private long getPersistentSizeHighThreshold() - { - return _persistentSizeHighThreshold; - } - - private void setEnvironmentConfigProperties(EnvironmentConfig envConfig) - { - for (Map.Entry<String, String> configItem : _envConfigMap.entrySet()) - { - LOGGER.debug("Setting EnvironmentConfig key " + configItem.getKey() + " to '" + configItem.getValue() + "'"); - envConfig.setConfigParam(configItem.getKey(), configItem.getValue()); - } - } - - protected EnvironmentConfig createEnvironmentConfig() - { - EnvironmentConfig envConfig = new EnvironmentConfig(); - envConfig.setAllowCreate(true); - envConfig.setTransactional(true); - - setEnvironmentConfigProperties(envConfig); - - envConfig.setExceptionListener(new LoggingAsyncExceptionListener()); - - return envConfig; - } - - protected void closeEnvironmentSafely() - { - try - { - _environment.close(); - } - catch (DatabaseException ex) - { - LOGGER.error("Exception closing store environment", ex); - } - catch (IllegalStateException ex) - { - LOGGER.error("Exception closing store environment", ex); - } - } - - - private class LoggingAsyncExceptionListener implements ExceptionListener - { - @Override - public void exceptionThrown(ExceptionEvent event) - { - LOGGER.error("Asynchronous exception thrown by BDB thread '" - + event.getThreadName() + "'", event.getException()); - } - } - - @Override - public void onDelete() - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Deleting store " + _storeLocation); - } - - if (_storeLocation != null) - { - File location = new File(_storeLocation); - if (location.exists()) - { - if (!FileUtils.delete(location, true)) - { - LOGGER.error("Cannot delete " + _storeLocation); - } - } - } - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStore.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStore.java deleted file mode 100644 index d99733acf0..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStore.java +++ /dev/null @@ -1,665 +0,0 @@ -/* - * 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 java.io.File; -import java.net.InetSocketAddress; -import java.security.PrivilegedAction; -import java.util.ArrayList; -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.concurrent.Callable; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.log4j.Logger; -import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.security.auth.TaskPrincipal; -import org.apache.qpid.server.store.StoreException; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.store.HAMessageStore; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.MessageStoreRecoveryHandler; -import org.apache.qpid.server.store.State; -import org.apache.qpid.server.store.StoreFuture; -import org.apache.qpid.server.store.TransactionLogRecoveryHandler; - -import com.sleepycat.je.DatabaseException; -import com.sleepycat.je.Durability; -import com.sleepycat.je.Durability.ReplicaAckPolicy; -import com.sleepycat.je.Durability.SyncPolicy; -import com.sleepycat.je.Environment; -import com.sleepycat.je.EnvironmentConfig; -import com.sleepycat.je.OperationFailureException; -import com.sleepycat.je.Transaction; -import com.sleepycat.je.rep.InsufficientLogException; -import com.sleepycat.je.rep.NetworkRestore; -import com.sleepycat.je.rep.NetworkRestoreConfig; -import com.sleepycat.je.rep.ReplicatedEnvironment; -import com.sleepycat.je.rep.ReplicationConfig; -import com.sleepycat.je.rep.ReplicationMutableConfig; -import com.sleepycat.je.rep.ReplicationNode; -import com.sleepycat.je.rep.StateChangeEvent; -import com.sleepycat.je.rep.StateChangeListener; -import com.sleepycat.je.rep.util.ReplicationGroupAdmin; - -import javax.security.auth.Subject; - -public class BDBHAMessageStore extends AbstractBDBMessageStore implements HAMessageStore -{ - private static final Logger LOGGER = Logger.getLogger(BDBHAMessageStore.class); - - private static final Durability DEFAULT_DURABILITY = new Durability(SyncPolicy.NO_SYNC, SyncPolicy.NO_SYNC, ReplicaAckPolicy.SIMPLE_MAJORITY); - - public static final String GRP_MEM_COL_NODE_HOST_PORT = "NodeHostPort"; - public static final String GRP_MEM_COL_NODE_NAME = "NodeName"; - - @SuppressWarnings("serial") - private static final Map<String, String> REPCONFIG_DEFAULTS = Collections.unmodifiableMap(new HashMap<String, String>() - {{ - /** - * Parameter decreased as the 24h default may lead very large log files for most users. - */ - put(ReplicationConfig.REP_STREAM_TIMEOUT, "1 h"); - /** - * Parameter increased as the 5 s default may lead to spurious timeouts. - */ - put(ReplicationConfig.REPLICA_ACK_TIMEOUT, "15 s"); - /** - * Parameter increased as the 10 s default may lead to spurious timeouts. - */ - put(ReplicationConfig.INSUFFICIENT_REPLICAS_TIMEOUT, "20 s"); - /** - * Parameter increased as the 10 h default may cause user confusion. - */ - put(ReplicationConfig.ENV_SETUP_TIMEOUT, "15 min"); - /** - * Parameter changed from default true so we adopt immediately adopt the new behaviour early. False - * is scheduled to become default after JE 5.0.48. - */ - put(ReplicationConfig.PROTOCOL_OLD_STRING_ENCODING, Boolean.FALSE.toString()); - /** - * Parameter decreased as a default 5min interval may lead to bigger data losses on Node - * with NO_SYN durability in case if such Node crushes. - */ - put(ReplicationConfig.LOG_FLUSH_TASK_INTERVAL, "1 min"); - }}); - - public static final String TYPE = "BDB-HA"; - - private String _groupName; - private String _nodeName; - private String _nodeHostPort; - private String _helperHostPort; - private Durability _durability; - - private String _name; - - private CommitThreadWrapper _commitThreadWrapper; - private boolean _coalescingSync; - private boolean _designatedPrimary; - private Map<String, String> _repConfig; - - @Override - public void configure(VirtualHost virtualHost) - { - //Mandatory configuration - _groupName = getValidatedStringAttribute(virtualHost, "haGroupName"); - _nodeName = getValidatedStringAttribute(virtualHost, "haNodeName"); - _nodeHostPort = getValidatedStringAttribute(virtualHost, "haNodeAddress"); - _helperHostPort = getValidatedStringAttribute(virtualHost, "haHelperAddress"); - _name = virtualHost.getName(); - - //Optional configuration - String durabilitySetting = getStringAttribute(virtualHost,"haDurability",null); - if (durabilitySetting == null) - { - _durability = DEFAULT_DURABILITY; - } - else - { - _durability = Durability.parse(durabilitySetting); - } - _designatedPrimary = getBooleanAttribute(virtualHost, "haDesignatedPrimary", Boolean.FALSE); - _coalescingSync = getBooleanAttribute(virtualHost, "haCoalescingSync", Boolean.TRUE); - - _repConfig = new HashMap<String, String>(REPCONFIG_DEFAULTS); - Object repConfigAttr = virtualHost.getAttribute("haReplicationConfig"); - if(repConfigAttr instanceof Map) - { - _repConfig.putAll((Map)repConfigAttr); - } - - if (_coalescingSync && _durability.getLocalSync() == SyncPolicy.SYNC) - { - throw new StoreException("Coalescing sync cannot be used with master sync policy " + SyncPolicy.SYNC - + "! Please set highAvailability.coalescingSync to false in store configuration."); - } - - super.configure(virtualHost); - } - - - private String getValidatedStringAttribute(org.apache.qpid.server.model.VirtualHost virtualHost, String attributeName) - { - Object attrValue = virtualHost.getAttribute(attributeName); - if(attrValue != null) - { - return attrValue.toString(); - } - else - { - throw new StoreException("BDB HA configuration key not found. Please specify configuration attribute: " - + attributeName); - } - } - - private String getStringAttribute(org.apache.qpid.server.model.VirtualHost virtualHost, String attributeName, String defaultVal) - { - Object attrValue = virtualHost.getAttribute(attributeName); - if(attrValue != null) - { - return attrValue.toString(); - } - return defaultVal; - } - - private boolean getBooleanAttribute(org.apache.qpid.server.model.VirtualHost virtualHost, String attributeName, boolean defaultVal) - { - Object attrValue = virtualHost.getAttribute(attributeName); - if(attrValue != null) - { - if(attrValue instanceof Boolean) - { - return ((Boolean) attrValue).booleanValue(); - } - else if(attrValue instanceof String) - { - return Boolean.parseBoolean((String)attrValue); - } - - } - return defaultVal; - } - - - @Override - protected void setupStore(File storePath, String name) throws DatabaseException - { - super.setupStore(storePath, name); - - if(_coalescingSync) - { - _commitThreadWrapper = new CommitThreadWrapper("Commit-Thread-" + name, getEnvironment()); - _commitThreadWrapper.startCommitThread(); - } - } - - @Override - protected Environment createEnvironment(File environmentPath) throws DatabaseException - { - if (LOGGER.isInfoEnabled()) - { - LOGGER.info("Environment path " + environmentPath.getAbsolutePath()); - LOGGER.info("Group name " + _groupName); - LOGGER.info("Node name " + _nodeName); - LOGGER.info("Node host port " + _nodeHostPort); - LOGGER.info("Helper host port " + _helperHostPort); - LOGGER.info("Durability " + _durability); - LOGGER.info("Coalescing sync " + _coalescingSync); - LOGGER.info("Designated primary (applicable to 2 node case only) " + _designatedPrimary); - } - - final ReplicationConfig replicationConfig = new ReplicationConfig(_groupName, _nodeName, _nodeHostPort); - - replicationConfig.setHelperHosts(_helperHostPort); - replicationConfig.setDesignatedPrimary(_designatedPrimary); - setReplicationConfigProperties(replicationConfig); - - final EnvironmentConfig envConfig = createEnvironmentConfig(); - envConfig.setDurability(_durability); - - ReplicatedEnvironment replicatedEnvironment = null; - try - { - replicatedEnvironment = new ReplicatedEnvironment(environmentPath, replicationConfig, envConfig); - } - catch (final InsufficientLogException ile) - { - LOGGER.info("InsufficientLogException thrown and so full network restore required", ile); - NetworkRestore restore = new NetworkRestore(); - NetworkRestoreConfig config = new NetworkRestoreConfig(); - config.setRetainLogFiles(false); - restore.execute(ile, config); - replicatedEnvironment = new ReplicatedEnvironment(environmentPath, replicationConfig, envConfig); - } - - return replicatedEnvironment; - } - - @Override - public void configureMessageStore(VirtualHost virtualHost, MessageStoreRecoveryHandler messageRecoveryHandler, - TransactionLogRecoveryHandler tlogRecoveryHandler) - { - super.configureMessageStore(virtualHost, messageRecoveryHandler, tlogRecoveryHandler); - - final ReplicatedEnvironment replicatedEnvironment = getReplicatedEnvironment(); - - replicatedEnvironment.setStateChangeListener(new BDBHAMessageStoreStateChangeListener()); - } - - @Override - public synchronized void activate() - { - // Before proceeding, perform a log flush with an fsync - getEnvironment().flushLog(true); - - super.activate(); - } - - @Override - public synchronized void passivate() - { - if (_stateManager.isNotInState(State.INITIALISED)) - { - LOGGER.debug("Store becoming passive"); - _stateManager.attainState(State.INITIALISED); - } - } - - public String getName() - { - return _name; - } - - public String getGroupName() - { - return _groupName; - } - - public String getNodeName() - { - return _nodeName; - } - - public String getNodeHostPort() - { - return _nodeHostPort; - } - - public String getHelperHostPort() - { - return _helperHostPort; - } - - public String getDurability() - { - return _durability.toString(); - } - - public boolean isCoalescingSync() - { - return _coalescingSync; - } - - public String getNodeState() - { - ReplicatedEnvironment.State state = getReplicatedEnvironment().getState(); - return state.toString(); - } - - public Boolean isDesignatedPrimary() - { - return getReplicatedEnvironment().getRepMutableConfig().getDesignatedPrimary(); - } - - public List<Map<String, String>> getGroupMembers() - { - List<Map<String, String>> members = new ArrayList<Map<String,String>>(); - - for (ReplicationNode node : getReplicatedEnvironment().getGroup().getNodes()) - { - Map<String, String> nodeMap = new HashMap<String, String>(); - nodeMap.put(BDBHAMessageStore.GRP_MEM_COL_NODE_NAME, node.getName()); - nodeMap.put(BDBHAMessageStore.GRP_MEM_COL_NODE_HOST_PORT, node.getHostName() + ":" + node.getPort()); - members.add(nodeMap); - } - - return members; - } - - public void removeNodeFromGroup(String nodeName) throws StoreException - { - try - { - createReplicationGroupAdmin().removeMember(nodeName); - } - catch (OperationFailureException ofe) - { - throw new StoreException("Failed to remove '" + nodeName + "' from group. " + ofe.getMessage(), ofe); - } - catch (DatabaseException e) - { - throw new StoreException("Failed to remove '" + nodeName + "' from group. " + e.getMessage(), e); - } - } - - public void setDesignatedPrimary(boolean isPrimary) throws StoreException - { - try - { - final ReplicatedEnvironment replicatedEnvironment = getReplicatedEnvironment(); - synchronized(replicatedEnvironment) - { - final ReplicationMutableConfig oldConfig = replicatedEnvironment.getRepMutableConfig(); - final ReplicationMutableConfig newConfig = oldConfig.setDesignatedPrimary(isPrimary); - replicatedEnvironment.setRepMutableConfig(newConfig); - } - - if (LOGGER.isInfoEnabled()) - { - LOGGER.info("Node " + _nodeName + " successfully set as designated primary for group"); - } - } - catch (DatabaseException e) - { - throw new StoreException("Failed to set '" + _nodeName + "' as designated primary for group. " + e.getMessage(), e); - } - } - - ReplicatedEnvironment getReplicatedEnvironment() - { - return (ReplicatedEnvironment)getEnvironment(); - } - - public void updateAddress(String nodeName, String newHostName, int newPort) throws StoreException - { - try - { - createReplicationGroupAdmin().updateAddress(nodeName, newHostName, newPort); - } - catch (OperationFailureException ofe) - { - throw new StoreException("Failed to update address for '" + nodeName + - "' with new host " + newHostName + " and new port " + newPort + ". " + ofe.getMessage(), ofe); - } - catch (DatabaseException e) - { - throw new StoreException("Failed to update address for '" + nodeName + - "' with new host " + newHostName + " and new port " + newPort + ". " + e.getMessage(), e); - } - } - - @Override - protected StoreFuture commit(Transaction tx, boolean syncCommit) throws DatabaseException - { - // Using commit() instead of commitNoSync() for the HA store to allow - // the HA durability configuration to influence resulting behaviour. - try - { - tx.commit(); - } - catch (DatabaseException de) - { - LOGGER.error("Got DatabaseException on commit, closing environment", de); - - closeEnvironmentSafely(); - - throw de; - } - - if(_coalescingSync) - { - return _commitThreadWrapper.commit(tx, syncCommit); - } - else - { - return StoreFuture.IMMEDIATE_FUTURE; - } - } - - @Override - protected void closeInternal() - { - substituteNoOpStateChangeListenerOn(getReplicatedEnvironment()); - - try - { - if(_coalescingSync) - { - try - { - _commitThreadWrapper.stopCommitThread(); - } - catch (InterruptedException e) - { - throw new StoreException(e); - } - } - } - finally - { - super.closeInternal(); - } - } - - /** - * Replicas emit a state change event {@link com.sleepycat.je.rep.ReplicatedEnvironment.State#DETACHED} during - * {@link Environment#close()}. We replace the StateChangeListener so we silently ignore this state change. - */ - private void substituteNoOpStateChangeListenerOn(ReplicatedEnvironment replicatedEnvironment) - { - LOGGER.debug("Substituting no-op state change listener for environment close"); - replicatedEnvironment.setStateChangeListener(new NoOpStateChangeListener()); - } - - private ReplicationGroupAdmin createReplicationGroupAdmin() - { - final Set<InetSocketAddress> helpers = new HashSet<InetSocketAddress>(); - helpers.addAll(getReplicatedEnvironment().getRepConfig().getHelperSockets()); - - final ReplicationConfig repConfig = getReplicatedEnvironment().getRepConfig(); - helpers.add(InetSocketAddress.createUnresolved(repConfig.getNodeHostname(), repConfig.getNodePort())); - - return new ReplicationGroupAdmin(_groupName, helpers); - } - - - private void setReplicationConfigProperties(ReplicationConfig replicationConfig) - { - for (Map.Entry<String, String> configItem : _repConfig.entrySet()) - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Setting ReplicationConfig key " + configItem.getKey() + " to '" + configItem.getValue() + "'"); - } - replicationConfig.setConfigParam(configItem.getKey(), configItem.getValue()); - } - } - - private String getValidatedPropertyFromConfig(String key, Configuration config) throws ConfigurationException - { - if (!config.containsKey(key)) - { - throw new ConfigurationException("BDB HA configuration key not found. Please specify configuration key with XPath: " - + key.replace('.', '/')); - } - return config.getString(key); - } - - private class BDBHAMessageStoreStateChangeListener implements StateChangeListener - { - private final Executor _executor = Executors.newSingleThreadExecutor(); - - @Override - public void stateChange(StateChangeEvent stateChangeEvent) - { - com.sleepycat.je.rep.ReplicatedEnvironment.State state = stateChangeEvent.getState(); - - if (LOGGER.isInfoEnabled()) - { - LOGGER.info("Received BDB event indicating transition to state " + state); - } - - switch (state) - { - case MASTER: - activateStoreAsync(); - break; - case REPLICA: - passivateStoreAsync(); - break; - case DETACHED: - LOGGER.error("BDB replicated node in detached state, therefore passivating."); - passivateStoreAsync(); - break; - case UNKNOWN: - LOGGER.warn("BDB replicated node in unknown state (hopefully temporarily)"); - break; - default: - LOGGER.error("Unexpected state change: " + state); - throw new IllegalStateException("Unexpected state change: " + state); - } - } - - /** - * Calls {@link MessageStore#activate()}. - * - * <p/> - * - * This is done a background thread, in line with - * {@link StateChangeListener#stateChange(StateChangeEvent)}'s JavaDoc, because - * activate may execute transactions, which can't complete until - * {@link StateChangeListener#stateChange(StateChangeEvent)} has returned. - */ - private void activateStoreAsync() - { - String threadName = "BDBHANodeActivationThread-" + _name; - executeStateChangeAsync(new Callable<Void>() - { - @Override - public Void call() throws Exception - { - try - { - activate(); - } - catch (Exception e) - { - LOGGER.error("Failed to activate on hearing MASTER change event",e); - throw e; - } - return null; - } - }, threadName); - } - - /** - * Calls {@link #passivate()}. - * - * <p/> - * This is done a background thread, in line with - * {@link StateChangeListener#stateChange(StateChangeEvent)}'s JavaDoc, because - * passivation due to the effect of state change listeners. - */ - private void passivateStoreAsync() - { - String threadName = "BDBHANodePassivationThread-" + _name; - executeStateChangeAsync(new Callable<Void>() - { - - @Override - public Void call() throws Exception - { - try - { - passivate(); - } - catch (Exception e) - { - LOGGER.error("Failed to passivate on hearing REPLICA or DETACHED change event",e); - throw e; - } - return null; - } - }, threadName); - } - - private void executeStateChangeAsync(final Callable<Void> callable, final String threadName) - { - - _executor.execute(new Runnable() - { - - @Override - public void run() - { - final String originalThreadName = Thread.currentThread().getName(); - Thread.currentThread().setName(threadName); - - try - { - Subject.doAs(SecurityManager.getSystemTaskSubject("BDB HA State Change"), new PrivilegedAction<Object>() - { - @Override - public Object run() - { - - try - { - callable.call(); - } - catch (Exception e) - { - LOGGER.error("Exception during state change", e); - } - return null; - } - }); - } - finally - { - Thread.currentThread().setName(originalThreadName); - } - } - }); - } - } - - private class NoOpStateChangeListener implements StateChangeListener - { - @Override - public void stateChange(StateChangeEvent stateChangeEvent) - { - } - } - - @Override - public String getStoreType() - { - return TYPE; - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHost.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHost.java index b055f8bd90..e41b81f846 100644 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHost.java +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHost.java @@ -20,7 +20,7 @@ package org.apache.qpid.server.store.berkeleydb; * */ -import org.apache.qpid.server.configuration.VirtualHostConfiguration; +import org.apache.log4j.Logger; import org.apache.qpid.server.connection.IConnectionRegistry; import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; import org.apache.qpid.server.model.VirtualHost; @@ -31,32 +31,36 @@ import org.apache.qpid.server.store.Event; import org.apache.qpid.server.store.EventListener; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.OperationalLoggingListener; +import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacade; +import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacadeFactory; import org.apache.qpid.server.virtualhost.AbstractVirtualHost; import org.apache.qpid.server.virtualhost.DefaultUpgraderProvider; import org.apache.qpid.server.virtualhost.State; import org.apache.qpid.server.virtualhost.VirtualHostConfigRecoveryHandler; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; +import com.sleepycat.je.rep.StateChangeEvent; +import com.sleepycat.je.rep.StateChangeListener; + public class BDBHAVirtualHost extends AbstractVirtualHost { - private BDBHAMessageStore _messageStore; + private static final Logger LOGGER = Logger.getLogger(BDBHAVirtualHost.class); + + private BDBMessageStore _messageStore; private boolean _inVhostInitiatedClose; BDBHAVirtualHost(VirtualHostRegistry virtualHostRegistry, StatisticsGatherer brokerStatisticsGatherer, org.apache.qpid.server.security.SecurityManager parentSecurityManager, - VirtualHostConfiguration hostConfig, VirtualHost virtualHost) { - super(virtualHostRegistry, brokerStatisticsGatherer, parentSecurityManager, hostConfig, virtualHost); + super(virtualHostRegistry, brokerStatisticsGatherer, parentSecurityManager, virtualHost); } - - - protected void initialiseStorage(VirtualHostConfiguration hostConfig, VirtualHost virtualHost) + protected void initialiseStorage(VirtualHost virtualHost) { - _messageStore = new BDBHAMessageStore(); + _messageStore = new BDBMessageStore(new ReplicatedEnvironmentFacadeFactory()); final MessageStoreLogSubject storeLogSubject = new MessageStoreLogSubject(getName(), _messageStore.getClass().getSimpleName()); @@ -84,6 +88,11 @@ public class BDBHAVirtualHost extends AbstractVirtualHost virtualHost, recoveryHandler, recoveryHandler ); + + // Make the virtualhost model object a replication group listener + ReplicatedEnvironmentFacade environmentFacade = (ReplicatedEnvironmentFacade) _messageStore.getEnvironmentFacade(); + environmentFacade.setStateChangeListener(new BDBHAMessageStoreStateChangeListener()); + } @@ -168,7 +177,7 @@ public class BDBHAVirtualHost extends AbstractVirtualHost @Override public void event(Event event) { - initialiseModel(getConfiguration()); + initialiseModel(); } } @@ -194,4 +203,70 @@ public class BDBHAVirtualHost extends AbstractVirtualHost } } + private class BDBHAMessageStoreStateChangeListener implements StateChangeListener + { + + @Override + public void stateChange(StateChangeEvent stateChangeEvent) throws RuntimeException + { + com.sleepycat.je.rep.ReplicatedEnvironment.State state = stateChangeEvent.getState(); + + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("Received BDB event indicating transition to state " + state + + " when current message store state is " + _messageStore._stateManager.getState()); + } + + switch (state) + { + case MASTER: + activate(); + break; + case REPLICA: + passivate(); + break; + case DETACHED: + LOGGER.error("BDB replicated node in detached state, therefore passivating."); + passivate(); + break; + case UNKNOWN: + LOGGER.warn("BDB replicated node in unknown state (hopefully temporarily)"); + break; + default: + LOGGER.error("Unexpected state change: " + state); + throw new IllegalStateException("Unexpected state change: " + state); + } + } + + private void activate() + { + try + { + _messageStore.getEnvironmentFacade().getEnvironment().flushLog(true); + _messageStore.activate(); + } + catch (Exception e) + { + LOGGER.error("Failed to activate on hearing MASTER change event", e); + } + } + + private void passivate() + { + try + { + //TODO: move this this into the store method passivate() + if (_messageStore._stateManager.isNotInState(org.apache.qpid.server.store.State.INITIALISED)) + { + _messageStore._stateManager.attainState(org.apache.qpid.server.store.State.INITIALISED); + } + } + catch (Exception e) + { + LOGGER.error("Failed to passivate on hearing REPLICA or DETACHED change event", e); + } + } + + } + } diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostFactory.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostFactory.java index 7a308920b3..6fb84b8a4d 100644 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostFactory.java +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostFactory.java @@ -19,16 +19,12 @@ package org.apache.qpid.server.store.berkeleydb;/* * */ -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; -import org.apache.commons.configuration.Configuration; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; -import org.apache.qpid.server.model.adapter.VirtualHostAdapter; + import org.apache.qpid.server.plugin.VirtualHostFactory; import org.apache.qpid.server.stats.StatisticsGatherer; -import org.apache.qpid.server.store.MessageStoreConstants; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacadeFactory; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; @@ -47,24 +43,29 @@ public class BDBHAVirtualHostFactory implements VirtualHostFactory public VirtualHost createVirtualHost(VirtualHostRegistry virtualHostRegistry, StatisticsGatherer brokerStatisticsGatherer, org.apache.qpid.server.security.SecurityManager parentSecurityManager, - VirtualHostConfiguration hostConfig, org.apache.qpid.server.model.VirtualHost virtualHost) { return new BDBHAVirtualHost(virtualHostRegistry, brokerStatisticsGatherer, parentSecurityManager, - hostConfig, virtualHost); } @Override public void validateAttributes(Map<String, Object> attributes) { - validateAttribute(org.apache.qpid.server.model.VirtualHost.STORE_PATH, String.class, attributes); - validateAttribute("haGroupName", String.class, attributes); - validateAttribute("haNodeName", String.class, attributes); - validateAttribute("haNodeAddress", String.class, attributes); - validateAttribute("haHelperAddress", String.class, attributes); + @SuppressWarnings("unchecked") + Map<String, Object> messageStoreSettings = (Map<String, Object>)attributes.get(org.apache.qpid.server.model.VirtualHost.MESSAGE_STORE_SETTINGS); + if (messageStoreSettings == null) + { + throw new IllegalArgumentException("Attribute '"+ org.apache.qpid.server.model.VirtualHost.MESSAGE_STORE_SETTINGS + "' is required."); + } + + validateAttribute(MessageStore.STORE_PATH, String.class, messageStoreSettings); + validateAttribute(ReplicatedEnvironmentFacadeFactory.GROUP_NAME, String.class, messageStoreSettings); + validateAttribute(ReplicatedEnvironmentFacadeFactory.NODE_NAME, String.class, messageStoreSettings); + validateAttribute(ReplicatedEnvironmentFacadeFactory.NODE_ADDRESS, String.class, messageStoreSettings); + validateAttribute(ReplicatedEnvironmentFacadeFactory.HELPER_ADDRESS, String.class, messageStoreSettings); } private void validateAttribute(String attrName, Class<?> clazz, Map<String, Object> attributes) @@ -77,82 +78,4 @@ public class BDBHAVirtualHostFactory implements VirtualHostFactory } } - @Override - public Map<String, Object> createVirtualHostConfiguration(VirtualHostAdapter virtualHostAdapter) - { - LinkedHashMap<String,Object> convertedMap = new LinkedHashMap<String, Object>(); - convertedMap.put("store.environment-path", virtualHostAdapter.getAttribute(org.apache.qpid.server.model.VirtualHost.STORE_PATH)); - - return convertedMap; - } - - public Map<String, Object> convertVirtualHostConfiguration(Configuration configuration) - { - - LinkedHashMap<String,Object> convertedMap = new LinkedHashMap<String, Object>(); - - Configuration storeConfiguration = configuration.subset("store"); - - convertedMap.put(org.apache.qpid.server.model.VirtualHost.STORE_PATH, storeConfiguration.getString(MessageStoreConstants.ENVIRONMENT_PATH_PROPERTY)); - convertedMap.put(MessageStoreConstants.OVERFULL_SIZE_ATTRIBUTE, storeConfiguration.getString(MessageStoreConstants.OVERFULL_SIZE_PROPERTY)); - convertedMap.put(MessageStoreConstants.UNDERFULL_SIZE_ATTRIBUTE, storeConfiguration.getString(MessageStoreConstants.UNDERFULL_SIZE_PROPERTY)); - convertedMap.put("haGroupName", configuration.getString("store.highAvailability.groupName")); - convertedMap.put("haNodeName", configuration.getString("store.highAvailability.nodeName")); - convertedMap.put("haNodeAddress", configuration.getString("store.highAvailability.nodeHostPort")); - convertedMap.put("haHelperAddress", configuration.getString("store.highAvailability.helperHostPort")); - - final Object haDurability = configuration.getString("store.highAvailability.durability"); - if(haDurability !=null) - { - convertedMap.put("haDurability", haDurability); - } - - final Object designatedPrimary = configuration.getString("store.highAvailability.designatedPrimary"); - if(designatedPrimary!=null) - { - convertedMap.put("haDesignatedPrimary", designatedPrimary); - } - - final Object coalescingSync = configuration.getString("store.highAvailability.coalescingSync"); - if(coalescingSync!=null) - { - convertedMap.put("haCoalescingSync", coalescingSync); - } - - - Map<String, String> attributes = getEnvironmentMap(storeConfiguration, "envConfig"); - - if(!attributes.isEmpty()) - { - convertedMap.put("bdbEnvironmentConfig",attributes); - } - - attributes = getEnvironmentMap(storeConfiguration, "repConfig"); - - if(!attributes.isEmpty()) - { - convertedMap.put("haReplicationConfig",attributes); - } - - return convertedMap; - - } - - private Map<String, String> getEnvironmentMap(Configuration storeConfiguration, String configName) - { - final List<Object> argumentNames = storeConfiguration.getList(configName +".name"); - final List<Object> argumentValues = storeConfiguration.getList(configName +".value"); - final int initialSize = argumentNames.size(); - - final Map<String,String> attributes = new HashMap<String,String>(initialSize); - - for (int i = 0; i < argumentNames.size(); i++) - { - final String argName = argumentNames.get(i).toString(); - final String argValue = argumentValues.get(i).toString(); - - attributes.put(argName, argValue); - } - return attributes; - } } diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java index acff8e2b21..8be037eb7b 100644 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java @@ -21,15 +21,68 @@ package org.apache.qpid.server.store.berkeleydb; import java.io.File; +import java.lang.ref.SoftReference; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; import org.apache.log4j.Logger; +import org.apache.qpid.server.message.EnqueueableMessage; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.store.ConfigurationRecoveryHandler; +import org.apache.qpid.server.store.ConfiguredObjectRecord; +import org.apache.qpid.server.store.DurableConfigurationStore; +import org.apache.qpid.server.store.Event; +import org.apache.qpid.server.store.EventListener; +import org.apache.qpid.server.store.EventManager; import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.MessageStoreRecoveryHandler; +import org.apache.qpid.server.store.MessageStoreRecoveryHandler.StoredMessageRecoveryHandler; +import org.apache.qpid.server.store.State; +import org.apache.qpid.server.store.StateManager; +import org.apache.qpid.server.store.StorableMessageMetaData; import org.apache.qpid.server.store.StoreException; import org.apache.qpid.server.store.StoreFuture; +import org.apache.qpid.server.store.StoredMemoryMessage; +import org.apache.qpid.server.store.StoredMessage; +import org.apache.qpid.server.store.TransactionLogRecoveryHandler; +import org.apache.qpid.server.store.TransactionLogRecoveryHandler.QueueEntryRecoveryHandler; +import org.apache.qpid.server.store.TransactionLogResource; +import org.apache.qpid.server.store.berkeleydb.entry.PreparedTransaction; +import org.apache.qpid.server.store.berkeleydb.entry.QueueEntryKey; +import org.apache.qpid.server.store.berkeleydb.entry.Xid; +import org.apache.qpid.server.store.berkeleydb.tuple.ConfiguredObjectBinding; +import org.apache.qpid.server.store.berkeleydb.tuple.ContentBinding; +import org.apache.qpid.server.store.berkeleydb.tuple.MessageMetaDataBinding; +import org.apache.qpid.server.store.berkeleydb.tuple.PreparedTransactionBinding; +import org.apache.qpid.server.store.berkeleydb.tuple.QueueEntryBinding; +import org.apache.qpid.server.store.berkeleydb.tuple.UUIDTupleBinding; +import org.apache.qpid.server.store.berkeleydb.tuple.XidBinding; +import org.apache.qpid.server.store.berkeleydb.upgrade.Upgrader; +import org.apache.qpid.util.FileUtils; +import com.sleepycat.bind.tuple.ByteBinding; +import com.sleepycat.bind.tuple.IntegerBinding; +import com.sleepycat.bind.tuple.LongBinding; +import com.sleepycat.je.CheckpointConfig; +import com.sleepycat.je.Cursor; +import com.sleepycat.je.Database; +import com.sleepycat.je.DatabaseConfig; +import com.sleepycat.je.DatabaseEntry; import com.sleepycat.je.DatabaseException; -import com.sleepycat.je.Environment; import com.sleepycat.je.EnvironmentConfig; +import com.sleepycat.je.LockConflictException; +import com.sleepycat.je.LockMode; +import com.sleepycat.je.OperationStatus; +import com.sleepycat.je.Transaction; /** * BDBMessageStore implements a persistent {@link MessageStore} using the BDB high performance log. @@ -39,83 +92,1616 @@ import com.sleepycat.je.EnvironmentConfig; * exchanges. <tr><td> Store and remove messages. <tr><td> Bind and unbind queues to exchanges. <tr><td> Enqueue and * dequeue messages to queues. <tr><td> Generate message identifiers. </table> */ -public class BDBMessageStore extends AbstractBDBMessageStore +public class BDBMessageStore implements MessageStore, DurableConfigurationStore { private static final Logger LOGGER = Logger.getLogger(BDBMessageStore.class); - public static final String TYPE = "BDB"; - private CommitThreadWrapper _commitThreadWrapper; + + public static final int VERSION = 7; + private static final int LOCK_RETRY_ATTEMPTS = 5; + private static String CONFIGURED_OBJECTS_DB_NAME = "CONFIGURED_OBJECTS"; + private static String MESSAGE_META_DATA_DB_NAME = "MESSAGE_METADATA"; + private static String MESSAGE_CONTENT_DB_NAME = "MESSAGE_CONTENT"; + private static String DELIVERY_DB_NAME = "QUEUE_ENTRIES"; + private static String BRIDGEDB_NAME = "BRIDGES"; + private static String LINKDB_NAME = "LINKS"; + private static String XID_DB_NAME = "XIDS"; + private static String CONFIG_VERSION_DB_NAME = "CONFIG_VERSION"; + private static final String[] DATABASE_NAMES = new String[] { CONFIGURED_OBJECTS_DB_NAME, MESSAGE_META_DATA_DB_NAME, + MESSAGE_CONTENT_DB_NAME, DELIVERY_DB_NAME, BRIDGEDB_NAME, LINKDB_NAME, XID_DB_NAME, CONFIG_VERSION_DB_NAME }; + + private final AtomicBoolean _closed = new AtomicBoolean(false); + + private EnvironmentFacade _environmentFacade; + private final AtomicLong _messageId = new AtomicLong(0); + + protected final StateManager _stateManager; + + private MessageStoreRecoveryHandler _messageRecoveryHandler; + + private TransactionLogRecoveryHandler _tlogRecoveryHandler; + + private ConfigurationRecoveryHandler _configRecoveryHandler; + + private long _totalStoreSize; + private boolean _limitBusted; + private long _persistentSizeLowThreshold; + private long _persistentSizeHighThreshold; + + private final EventManager _eventManager = new EventManager(); + private final String _type; + private VirtualHost _virtualHost; + + private final EnvironmentFacadeFactory _environmentFacadeFactory; + + private volatile Committer _committer; + + public BDBMessageStore() + { + this(new StandardEnvironmentFacadeFactory()); + } + + public BDBMessageStore(EnvironmentFacadeFactory environmentFacadeFactory) + { + _type = environmentFacadeFactory.getType(); + _environmentFacadeFactory = environmentFacadeFactory; + _stateManager = new StateManager(_eventManager); + } + + @Override + public void addEventListener(EventListener eventListener, Event... events) + { + _eventManager.addEventListener(eventListener, events); + } @Override - protected void setupStore(File storePath, String name) throws DatabaseException + public void configureConfigStore(VirtualHost virtualHost, ConfigurationRecoveryHandler recoveryHandler) { - super.setupStore(storePath, name); + _stateManager.attainState(State.INITIALISING); - _commitThreadWrapper = new CommitThreadWrapper("Commit-Thread-" + name, getEnvironment()); - _commitThreadWrapper.startCommitThread(); + _configRecoveryHandler = recoveryHandler; + _virtualHost = virtualHost; } - protected Environment createEnvironment(File environmentPath) throws DatabaseException + @Override + public void configureMessageStore(VirtualHost virtualHost, MessageStoreRecoveryHandler messageRecoveryHandler, + TransactionLogRecoveryHandler tlogRecoveryHandler) throws StoreException { - LOGGER.info("BDB message store using environment path " + environmentPath.getAbsolutePath()); - EnvironmentConfig envConfig = createEnvironmentConfig(); + if(_stateManager.isInState(State.INITIAL)) + { + // Is acting as a message store, but not a durable config store + _stateManager.attainState(State.INITIALISING); + } + + _messageRecoveryHandler = messageRecoveryHandler; + _tlogRecoveryHandler = tlogRecoveryHandler; + _virtualHost = virtualHost; + + + completeInitialisation(); + } + + private void completeInitialisation() throws StoreException + { + configure(_virtualHost, _messageRecoveryHandler != null); + + _stateManager.attainState(State.INITIALISED); + } + private void startActivation() throws StoreException + { + DatabaseConfig dbConfig = new DatabaseConfig(); + dbConfig.setTransactional(true); + dbConfig.setAllowCreate(true); try { - return new Environment(environmentPath, envConfig); + new Upgrader(_environmentFacade.getEnvironment(), _virtualHost.getName()).upgradeIfNecessary(); + _environmentFacade.openDatabases(dbConfig, DATABASE_NAMES); + _totalStoreSize = getSizeOnDisk(); + } + catch(DatabaseException e) + { + throw _environmentFacade.handleDatabaseException("Cannot configure store", e); + } + + } + + @Override + public synchronized void activate() throws StoreException + { + // check if acting as a durable config store, but not a message store + if(_stateManager.isInState(State.INITIALISING)) + { + completeInitialisation(); } - catch (DatabaseException de) + + _stateManager.attainState(State.ACTIVATING); + startActivation(); + + if(_configRecoveryHandler != null) + { + recoverConfig(_configRecoveryHandler); + } + if(_messageRecoveryHandler != null) + { + recoverMessages(_messageRecoveryHandler); + } + if(_tlogRecoveryHandler != null) + { + recoverQueueEntries(_tlogRecoveryHandler); + } + + _stateManager.attainState(State.ACTIVE); + } + + @Override + public org.apache.qpid.server.store.Transaction newTransaction() throws StoreException + { + return new BDBTransaction(); + } + + private void configure(VirtualHost virtualHost, boolean isMessageStore) throws StoreException + { + Map<String, Object> messageStoreSettings = virtualHost.getMessageStoreSettings(); + Object overfullAttr = messageStoreSettings.get(MessageStore.OVERFULL_SIZE); + Object underfullAttr = messageStoreSettings.get(MessageStore.UNDERFULL_SIZE); + + _persistentSizeHighThreshold = overfullAttr == null ? -1l : + overfullAttr instanceof Number ? ((Number) overfullAttr).longValue() : Long.parseLong(overfullAttr.toString()); + _persistentSizeLowThreshold = underfullAttr == null ? _persistentSizeHighThreshold : + underfullAttr instanceof Number ? ((Number) underfullAttr).longValue() : Long.parseLong(underfullAttr.toString()); + + + if(_persistentSizeLowThreshold > _persistentSizeHighThreshold || _persistentSizeLowThreshold < 0l) + { + _persistentSizeLowThreshold = _persistentSizeHighThreshold; + } + + _environmentFacade = _environmentFacadeFactory.createEnvironmentFacade(virtualHost, isMessageStore); + + _committer = _environmentFacade.createCommitter(virtualHost.getName()); + _committer.start(); + } + + @Override + public String getStoreLocation() + { + if (_environmentFacade == null) { - if (de.getMessage().contains("Environment.setAllowCreate is false")) + return null; + } + return _environmentFacade.getStoreLocation(); + } + + public EnvironmentFacade getEnvironmentFacade() + { + return _environmentFacade; + } + + /** + * Called to close and cleanup any resources used by the message store. + * + * @throws Exception If the close fails. + */ + @Override + public void close() throws StoreException + { + if (_closed.compareAndSet(false, true)) + { + _stateManager.attainState(State.CLOSING); + try { - //Allow the creation this time - envConfig.setAllowCreate(true); - return new Environment(environmentPath, envConfig); + try + { + _committer.stop(); + } + finally + { + closeEnvironment(); + } } - else + catch(DatabaseException e) + { + throw new StoreException("Exception occured on message store close", e); + } + _stateManager.attainState(State.CLOSED); + } + } + + private void closeEnvironment() + { + if (_environmentFacade != null) + { + _environmentFacade.close(); + } + } + + private void recoverConfig(ConfigurationRecoveryHandler recoveryHandler) throws StoreException + { + try + { + final int configVersion = getConfigVersion(); + recoveryHandler.beginConfigurationRecovery(this, configVersion); + loadConfiguredObjects(recoveryHandler); + + final int newConfigVersion = recoveryHandler.completeConfigurationRecovery(); + if(newConfigVersion != configVersion) + { + updateConfigVersion(newConfigVersion); + } + } + catch (DatabaseException e) + { + throw _environmentFacade.handleDatabaseException("Error recovering persistent state: " + e.getMessage(), e); + } + + } + + @SuppressWarnings("resource") + private void updateConfigVersion(int newConfigVersion) throws StoreException + { + Cursor cursor = null; + try + { + Transaction txn = _environmentFacade.getEnvironment().beginTransaction(null, null); + cursor = getConfigVersionDb().openCursor(txn, null); + DatabaseEntry key = new DatabaseEntry(); + ByteBinding.byteToEntry((byte) 0,key); + DatabaseEntry value = new DatabaseEntry(); + + while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) + { + IntegerBinding.intToEntry(newConfigVersion, value); + OperationStatus status = cursor.put(key, value); + if (status != OperationStatus.SUCCESS) + { + throw new StoreException("Error setting config version: " + status); + } + } + cursor.close(); + cursor = null; + txn.commit(); + } + finally + { + closeCursorSafely(cursor); + } + + } + + private int getConfigVersion() throws StoreException + { + Cursor cursor = null; + try + { + cursor = getConfigVersionDb().openCursor(null, null); + DatabaseEntry key = new DatabaseEntry(); + DatabaseEntry value = new DatabaseEntry(); + while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) + { + return IntegerBinding.entryToInt(value); + } + + // Insert 0 as the default config version + IntegerBinding.intToEntry(0,value); + ByteBinding.byteToEntry((byte) 0,key); + OperationStatus status = getConfigVersionDb().put(null, key, value); + if (status != OperationStatus.SUCCESS) + { + throw new StoreException("Error initialising config version: " + status); + } + return 0; + } + finally + { + closeCursorSafely(cursor); + } + } + + private void loadConfiguredObjects(ConfigurationRecoveryHandler crh) throws DatabaseException, StoreException + { + Cursor cursor = null; + try + { + cursor = getConfiguredObjectsDb().openCursor(null, null); + DatabaseEntry key = new DatabaseEntry(); + DatabaseEntry value = new DatabaseEntry(); + while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) + { + UUID id = UUIDTupleBinding.getInstance().entryToObject(key); + + ConfiguredObjectRecord configuredObject = new ConfiguredObjectBinding(id).entryToObject(value); + crh.configuredObject(configuredObject.getId(),configuredObject.getType(),configuredObject.getAttributes()); + } + + } + finally + { + closeCursorSafely(cursor); + } + } + + private void closeCursorSafely(Cursor cursor) throws StoreException + { + if (cursor != null) + { + try + { + cursor.close(); + } + catch(DatabaseException e) + { + throw _environmentFacade.handleDatabaseException("Cannot close cursor", e); + } + } + } + + + private void recoverMessages(MessageStoreRecoveryHandler msrh) throws StoreException + { + StoredMessageRecoveryHandler mrh = msrh.begin(); + + Cursor cursor = null; + try + { + cursor = getMessageMetaDataDb().openCursor(null, null); + DatabaseEntry key = new DatabaseEntry(); + DatabaseEntry value = new DatabaseEntry(); + MessageMetaDataBinding valueBinding = MessageMetaDataBinding.getInstance(); + + long maxId = 0; + + while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) { - throw de; + long messageId = LongBinding.entryToLong(key); + StorableMessageMetaData metaData = valueBinding.entryToObject(value); + + StoredBDBMessage message = new StoredBDBMessage(messageId, metaData, true); + + mrh.message(message); + + maxId = Math.max(maxId, messageId); } + + _messageId.set(maxId); + mrh.completeMessageRecovery(); + } + catch (DatabaseException e) + { + throw _environmentFacade.handleDatabaseException("Cannot recover messages", e); + } + finally + { + closeCursorSafely(cursor); + } + } + + private void recoverQueueEntries(TransactionLogRecoveryHandler recoveryHandler) + throws StoreException + { + QueueEntryRecoveryHandler qerh = recoveryHandler.begin(this); + + ArrayList<QueueEntryKey> entries = new ArrayList<QueueEntryKey>(); + + Cursor cursor = null; + try + { + cursor = getDeliveryDb().openCursor(null, null); + DatabaseEntry key = new DatabaseEntry(); + QueueEntryBinding keyBinding = QueueEntryBinding.getInstance(); + + DatabaseEntry value = new DatabaseEntry(); + while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) + { + QueueEntryKey qek = keyBinding.entryToObject(key); + + entries.add(qek); + } + + try + { + cursor.close(); + } + finally + { + cursor = null; + } + + for(QueueEntryKey entry : entries) + { + UUID queueId = entry.getQueueId(); + long messageId = entry.getMessageId(); + qerh.queueEntry(queueId, messageId); + } + } + catch (DatabaseException e) + { + throw _environmentFacade.handleDatabaseException("Cannot recover queue entries", e); + } + finally + { + closeCursorSafely(cursor); + } + + TransactionLogRecoveryHandler.DtxRecordRecoveryHandler dtxrh = qerh.completeQueueEntryRecovery(); + + cursor = null; + try + { + cursor = getXidDb().openCursor(null, null); + DatabaseEntry key = new DatabaseEntry(); + XidBinding keyBinding = XidBinding.getInstance(); + PreparedTransactionBinding valueBinding = new PreparedTransactionBinding(); + DatabaseEntry value = new DatabaseEntry(); + + while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) + { + Xid xid = keyBinding.entryToObject(key); + PreparedTransaction preparedTransaction = valueBinding.entryToObject(value); + dtxrh.dtxRecord(xid.getFormat(),xid.getGlobalId(),xid.getBranchId(), + preparedTransaction.getEnqueues(),preparedTransaction.getDequeues()); + } + + } + catch (DatabaseException e) + { + throw _environmentFacade.handleDatabaseException("Cannot recover transactions", e); + } + finally + { + closeCursorSafely(cursor); + } + + + dtxrh.completeDtxRecordRecovery(); + } + + public void removeMessage(long messageId, boolean sync) throws StoreException + { + + boolean complete = false; + com.sleepycat.je.Transaction tx = null; + + Random rand = null; + int attempts = 0; + try + { + do + { + tx = null; + try + { + tx = _environmentFacade.getEnvironment().beginTransaction(null, null); + + //remove the message meta data from the store + DatabaseEntry key = new DatabaseEntry(); + LongBinding.longToEntry(messageId, key); + + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Removing message id " + messageId); + } + + + OperationStatus status = getMessageMetaDataDb().delete(tx, key); + if (status == OperationStatus.NOTFOUND) + { + LOGGER.info("Message not found (attempt to remove failed - probably application initiated rollback) " + + messageId); + } + + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Deleted metadata for message " + messageId); + } + + //now remove the content data from the store if there is any. + DatabaseEntry contentKeyEntry = new DatabaseEntry(); + LongBinding.longToEntry(messageId, contentKeyEntry); + getMessageContentDb().delete(tx, contentKeyEntry); + + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Deleted content for message " + messageId); + } + + _environmentFacade.commit(tx); + _committer.commit(tx, sync); + + complete = true; + tx = null; + } + catch (LockConflictException e) + { + try + { + if(tx != null) + { + tx.abort(); + } + } + catch(DatabaseException e2) + { + LOGGER.warn("Unable to abort transaction after LockConflictExcption on removal of message with id " + messageId, e2); + // rethrow the original log conflict exception, the secondary exception should already have + // been logged. + throw _environmentFacade.handleDatabaseException("Cannot remove message with id " + messageId, e); + } + + + LOGGER.warn("Lock timeout exception. Retrying (attempt " + + (attempts+1) + " of "+ LOCK_RETRY_ATTEMPTS +") " + e); + + if(++attempts < LOCK_RETRY_ATTEMPTS) + { + if(rand == null) + { + rand = new Random(); + } + + try + { + Thread.sleep(500l + (long)(500l * rand.nextDouble())); + } + catch (InterruptedException e1) + { + + } + } + else + { + // rethrow the lock conflict exception since we could not solve by retrying + throw _environmentFacade.handleDatabaseException("Cannot remove messages", e); + } + } + } + while(!complete); + } + catch (DatabaseException e) + { + LOGGER.error("Unexpected BDB exception", e); + + try + { + abortTransactionIgnoringException("Error aborting transaction on removal of message with id " + messageId, tx); + } + finally + { + tx = null; + } + + throw _environmentFacade.handleDatabaseException("Error removing message with id " + messageId + " from database: " + e.getMessage(), e); + } + finally + { + try + { + abortTransactionIgnoringException("Error aborting transaction on removal of message with id " + messageId, tx); + } + finally + { + tx = null; + } + } + } + + private void abortTransactionIgnoringException(String errorMessage, com.sleepycat.je.Transaction tx) + { + try + { + if (tx != null) + { + tx.abort(); + } + } + catch (DatabaseException e1) + { + // We need the possible side effect of the handler restarting the environment but don't care about the exception + _environmentFacade.handleDatabaseException(null, e1); + LOGGER.warn(errorMessage, e1); } } @Override - protected void closeInternal() + public void create(UUID id, String type, Map<String, Object> attributes) throws StoreException + { + if (_stateManager.isInState(State.ACTIVE)) + { + ConfiguredObjectRecord configuredObject = new ConfiguredObjectRecord(id, type, attributes); + storeConfiguredObjectEntry(configuredObject); + } + } + + @Override + public void remove(UUID id, String type) throws StoreException + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("public void remove(id = " + id + ", type="+type+"): called"); + } + OperationStatus status = removeConfiguredObject(null, id); + if (status == OperationStatus.NOTFOUND) + { + throw new StoreException("Configured object of type " + type + " with id " + id + " not found"); + } + } + + @Override + public UUID[] removeConfiguredObjects(final UUID... objects) throws StoreException + { + com.sleepycat.je.Transaction txn = _environmentFacade.getEnvironment().beginTransaction(null, null); + Collection<UUID> removed = new ArrayList<UUID>(objects.length); + for(UUID id : objects) + { + if(removeConfiguredObject(txn, id) == OperationStatus.SUCCESS) + { + removed.add(id); + } + } + commitTransaction(txn); + return removed.toArray(new UUID[removed.size()]); + } + + private void commitTransaction(com.sleepycat.je.Transaction txn) throws StoreException { try { - _commitThreadWrapper.stopCommitThread(); + txn.commit(); } - catch (InterruptedException e) + catch(DatabaseException e) { - throw new StoreException(e); + throw _environmentFacade.handleDatabaseException("Cannot commit transaction on configured objects removal", e); } + } - super.closeInternal(); + @Override + public void update(UUID id, String type, Map<String, Object> attributes) throws StoreException + { + update(false, id, type, attributes, null); } @Override - protected StoreFuture commit(com.sleepycat.je.Transaction tx, boolean syncCommit) throws DatabaseException + public void update(boolean createIfNecessary, ConfiguredObjectRecord... records) throws StoreException { + com.sleepycat.je.Transaction txn = _environmentFacade.getEnvironment().beginTransaction(null, null); + for(ConfiguredObjectRecord record : records) + { + update(createIfNecessary, record.getId(), record.getType(), record.getAttributes(), txn); + } + commitTransaction(txn); + } + + private void update(boolean createIfNecessary, UUID id, String type, Map<String, Object> attributes, com.sleepycat.je.Transaction txn) throws StoreException + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Updating " +type + ", id: " + id); + } + try { - tx.commitNoSync(); + DatabaseEntry key = new DatabaseEntry(); + UUIDTupleBinding keyBinding = UUIDTupleBinding.getInstance(); + keyBinding.objectToEntry(id, key); + + DatabaseEntry value = new DatabaseEntry(); + DatabaseEntry newValue = new DatabaseEntry(); + ConfiguredObjectBinding configuredObjectBinding = ConfiguredObjectBinding.getInstance(); + + OperationStatus status = getConfiguredObjectsDb().get(txn, key, value, LockMode.DEFAULT); + if (status == OperationStatus.SUCCESS || (createIfNecessary && status == OperationStatus.NOTFOUND)) + { + ConfiguredObjectRecord newQueueRecord = new ConfiguredObjectRecord(id, type, attributes); + + // write the updated entry to the store + configuredObjectBinding.objectToEntry(newQueueRecord, newValue); + status = getConfiguredObjectsDb().put(txn, key, newValue); + if (status != OperationStatus.SUCCESS) + { + throw new StoreException("Error updating configuration details within the store: " + status); + } + } + else if (status != OperationStatus.NOTFOUND) + { + throw new StoreException("Error finding configuration details within the store: " + status); + } } - catch(DatabaseException de) + catch (DatabaseException e) { - LOGGER.error("Got DatabaseException on commit, closing environment", de); + if (txn != null) + { + abortTransactionIgnoringException("Error updating configuration details within the store: " + e.getMessage(), txn); + } + throw _environmentFacade.handleDatabaseException("Error updating configuration details within the store: " + e,e); + } + } + + /** + * Places a message onto a specified queue, in a given transaction. + * + * @param tx The transaction for the operation. + * @param queue The the queue to place the message on. + * @param messageId The message to enqueue. + * + * @throws StoreException If the operation fails for any reason. + */ + public void enqueueMessage(final com.sleepycat.je.Transaction tx, final TransactionLogResource queue, + long messageId) throws StoreException + { - closeEnvironmentSafely(); + DatabaseEntry key = new DatabaseEntry(); + QueueEntryBinding keyBinding = QueueEntryBinding.getInstance(); + QueueEntryKey dd = new QueueEntryKey(queue.getId(), messageId); + keyBinding.objectToEntry(dd, key); + DatabaseEntry value = new DatabaseEntry(); + ByteBinding.byteToEntry((byte) 0, value); - throw de; + try + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Enqueuing message " + messageId + " on queue " + + (queue instanceof AMQQueue ? ((AMQQueue) queue).getName() + " with id " : "") + queue.getId() + + " in transaction " + tx); + } + getDeliveryDb().put(tx, key, value); + } + catch (DatabaseException e) + { + LOGGER.error("Failed to enqueue: " + e.getMessage(), e); + throw _environmentFacade.handleDatabaseException("Error writing enqueued message with id " + messageId + " for queue " + + (queue instanceof AMQQueue ? ((AMQQueue) queue).getName() + " with id " : "") + queue.getId() + + " to database", e); } + } + + /** + * Extracts a message from a specified queue, in a given transaction. + * + * @param tx The transaction for the operation. + * @param queue The queue to take the message from. + * @param messageId The message to dequeue. + * + * @throws StoreException If the operation fails for any reason, or if the specified message does not exist. + */ + public void dequeueMessage(final com.sleepycat.je.Transaction tx, final TransactionLogResource queue, + long messageId) throws StoreException + { - return _commitThreadWrapper.commit(tx, syncCommit); + DatabaseEntry key = new DatabaseEntry(); + QueueEntryBinding keyBinding = QueueEntryBinding.getInstance(); + QueueEntryKey queueEntryKey = new QueueEntryKey(queue.getId(), messageId); + UUID id = queue.getId(); + keyBinding.objectToEntry(queueEntryKey, key); + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Dequeue message id " + messageId + " from queue " + + (queue instanceof AMQQueue ? ((AMQQueue) queue).getName() + " with id " : "") + id); + } + + try + { + + OperationStatus status = getDeliveryDb().delete(tx, key); + if (status == OperationStatus.NOTFOUND) + { + throw new StoreException("Unable to find message with id " + messageId + " on queue " + + (queue instanceof AMQQueue ? ((AMQQueue) queue).getName() + " with id " : "") + id); + } + else if (status != OperationStatus.SUCCESS) + { + throw new StoreException("Unable to remove message with id " + messageId + " on queue" + + (queue instanceof AMQQueue ? ((AMQQueue) queue).getName() + " with id " : "") + id); + } + + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Removed message " + messageId + " on queue " + + (queue instanceof AMQQueue ? ((AMQQueue) queue).getName() + " with id " : "") + id + + " from delivery db"); + + } + } + catch (DatabaseException e) + { + + LOGGER.error("Failed to dequeue message " + messageId + " in transaction " + tx , e); + + throw _environmentFacade.handleDatabaseException("Error accessing database while dequeuing message: " + e.getMessage(), e); + } + } + + + private void recordXid(com.sleepycat.je.Transaction txn, + long format, + byte[] globalId, + byte[] branchId, + org.apache.qpid.server.store.Transaction.Record[] enqueues, + org.apache.qpid.server.store.Transaction.Record[] dequeues) throws StoreException + { + DatabaseEntry key = new DatabaseEntry(); + Xid xid = new Xid(format, globalId, branchId); + XidBinding keyBinding = XidBinding.getInstance(); + keyBinding.objectToEntry(xid,key); + + DatabaseEntry value = new DatabaseEntry(); + PreparedTransaction preparedTransaction = new PreparedTransaction(enqueues, dequeues); + PreparedTransactionBinding valueBinding = new PreparedTransactionBinding(); + valueBinding.objectToEntry(preparedTransaction, value); + + try + { + getXidDb().put(txn, key, value); + } + catch (DatabaseException e) + { + LOGGER.error("Failed to write xid: " + e.getMessage(), e); + throw _environmentFacade.handleDatabaseException("Error writing xid to database", e); + } + } + + private void removeXid(com.sleepycat.je.Transaction txn, long format, byte[] globalId, byte[] branchId) + throws StoreException + { + DatabaseEntry key = new DatabaseEntry(); + Xid xid = new Xid(format, globalId, branchId); + XidBinding keyBinding = XidBinding.getInstance(); + + keyBinding.objectToEntry(xid, key); + + + try + { + + OperationStatus status = getXidDb().delete(txn, key); + if (status == OperationStatus.NOTFOUND) + { + throw new StoreException("Unable to find xid"); + } + else if (status != OperationStatus.SUCCESS) + { + throw new StoreException("Unable to remove xid"); + } + + } + catch (DatabaseException e) + { + + LOGGER.error("Failed to remove xid in transaction " + txn, e); + + throw _environmentFacade.handleDatabaseException("Error accessing database while removing xid: " + e.getMessage(), e); + } + } + + /** + * Commits all operations performed within a given transaction. + * + * @param tx The transaction to commit all operations for. + * + * @throws StoreException If the operation fails for any reason. + */ + private StoreFuture commitTranImpl(final com.sleepycat.je.Transaction tx, boolean syncCommit) throws StoreException + { + if (tx == null) + { + throw new StoreException("Fatal internal error: transactional is null at commitTran"); + } + + _environmentFacade.commit(tx); + StoreFuture result = _committer.commit(tx, syncCommit); + + if (LOGGER.isDebugEnabled()) + { + String transactionType = syncCommit ? "synchronous" : "asynchronous"; + LOGGER.debug("commitTranImpl completed " + transactionType + " transaction " + tx); + } + + return result; + } + + /** + * Abandons all operations performed within a given transaction. + * + * @param tx The transaction to abandon. + * + * @throws StoreException If the operation fails for any reason. + */ + public void abortTran(final com.sleepycat.je.Transaction tx) throws StoreException + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("abortTran called for transaction " + tx); + } + + try + { + tx.abort(); + } + catch (DatabaseException e) + { + throw _environmentFacade.handleDatabaseException("Error aborting transaction: " + e.getMessage(), e); + } + } + + /** + * Primarily for testing purposes. + * + * @param queueId + * + * @return a list of message ids for messages enqueued for a particular queue + */ + List<Long> getEnqueuedMessages(UUID queueId) throws StoreException + { + Cursor cursor = null; + try + { + cursor = getDeliveryDb().openCursor(null, null); + + DatabaseEntry key = new DatabaseEntry(); + + QueueEntryKey dd = new QueueEntryKey(queueId, 0); + + QueueEntryBinding keyBinding = QueueEntryBinding.getInstance(); + keyBinding.objectToEntry(dd, key); + + DatabaseEntry value = new DatabaseEntry(); + + LinkedList<Long> messageIds = new LinkedList<Long>(); + + OperationStatus status = cursor.getSearchKeyRange(key, value, LockMode.DEFAULT); + dd = keyBinding.entryToObject(key); + + while ((status == OperationStatus.SUCCESS) && dd.getQueueId().equals(queueId)) + { + + messageIds.add(dd.getMessageId()); + status = cursor.getNext(key, value, LockMode.DEFAULT); + if (status == OperationStatus.SUCCESS) + { + dd = keyBinding.entryToObject(key); + } + } + + return messageIds; + } + catch (DatabaseException e) + { + throw new StoreException("Database error: " + e.getMessage(), e); + } + finally + { + closeCursorSafely(cursor); + } + } + + /** + * Return a valid, currently unused message id. + * + * @return A fresh message id. + */ + public long getNewMessageId() + { + return _messageId.incrementAndGet(); + } + + /** + * Stores a chunk of message data. + * + * @param tx The transaction for the operation. + * @param messageId The message to store the data for. + * @param offset The offset of the data chunk in the message. + * @param contentBody The content of the data chunk. + * + * @throws StoreException If the operation fails for any reason, or if the specified message does not exist. + */ + protected void addContent(final com.sleepycat.je.Transaction tx, long messageId, int offset, + ByteBuffer contentBody) throws StoreException + { + DatabaseEntry key = new DatabaseEntry(); + LongBinding.longToEntry(messageId, key); + DatabaseEntry value = new DatabaseEntry(); + ContentBinding messageBinding = ContentBinding.getInstance(); + messageBinding.objectToEntry(contentBody.array(), value); + try + { + OperationStatus status = getMessageContentDb().put(tx, key, value); + if (status != OperationStatus.SUCCESS) + { + throw new StoreException("Error adding content for message id " + messageId + ": " + status); + } + + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Storing content for message " + messageId + " in transaction " + tx); + + } + } + catch (DatabaseException e) + { + throw _environmentFacade.handleDatabaseException("Error writing AMQMessage with id " + messageId + " to database: " + e.getMessage(), e); + } + } + + /** + * Stores message meta-data. + * + * @param tx The transaction for the operation. + * @param messageId The message to store the data for. + * @param messageMetaData The message meta data to store. + * + * @throws StoreException If the operation fails for any reason, or if the specified message does not exist. + */ + private void storeMetaData(final com.sleepycat.je.Transaction tx, long messageId, + StorableMessageMetaData messageMetaData) + throws StoreException + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("storeMetaData called for transaction " + tx + + ", messageId " + messageId + + ", messageMetaData " + messageMetaData); + } + + DatabaseEntry key = new DatabaseEntry(); + LongBinding.longToEntry(messageId, key); + DatabaseEntry value = new DatabaseEntry(); + + MessageMetaDataBinding messageBinding = MessageMetaDataBinding.getInstance(); + messageBinding.objectToEntry(messageMetaData, value); + try + { + getMessageMetaDataDb().put(tx, key, value); + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Storing message metadata for message id " + messageId + " in transaction " + tx); + } + } + catch (DatabaseException e) + { + throw _environmentFacade.handleDatabaseException("Error writing message metadata with id " + messageId + " to database: " + e.getMessage(), e); + } + } + + /** + * Retrieves message meta-data. + * + * @param messageId The message to get the meta-data for. + * + * @return The message meta data. + * + * @throws StoreException If the operation fails for any reason, or if the specified message does not exist. + */ + public StorableMessageMetaData getMessageMetaData(long messageId) throws StoreException + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("public MessageMetaData getMessageMetaData(Long messageId = " + + messageId + "): called"); + } + + DatabaseEntry key = new DatabaseEntry(); + LongBinding.longToEntry(messageId, key); + DatabaseEntry value = new DatabaseEntry(); + MessageMetaDataBinding messageBinding = MessageMetaDataBinding.getInstance(); + + try + { + OperationStatus status = getMessageMetaDataDb().get(null, key, value, LockMode.READ_UNCOMMITTED); + if (status != OperationStatus.SUCCESS) + { + throw new StoreException("Metadata not found for message with id " + messageId); + } + + StorableMessageMetaData mdd = messageBinding.entryToObject(value); + + return mdd; + } + catch (DatabaseException e) + { + throw _environmentFacade.handleDatabaseException("Error reading message metadata for message with id " + messageId + ": " + e.getMessage(), e); + } + } + + /** + * Fills the provided ByteBuffer with as much content for the specified message as possible, starting + * from the specified offset in the message. + * + * @param messageId The message to get the data for. + * @param offset The offset of the data within the message. + * @param dst The destination of the content read back + * + * @return The number of bytes inserted into the destination + * + * @throws StoreException If the operation fails for any reason, or if the specified message does not exist. + */ + public int getContent(long messageId, int offset, ByteBuffer dst) throws StoreException + { + DatabaseEntry contentKeyEntry = new DatabaseEntry(); + LongBinding.longToEntry(messageId, contentKeyEntry); + DatabaseEntry value = new DatabaseEntry(); + ContentBinding contentTupleBinding = ContentBinding.getInstance(); + + + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Message Id: " + messageId + " Getting content body from offset: " + offset); + } + + try + { + + int written = 0; + OperationStatus status = getMessageContentDb().get(null, contentKeyEntry, value, LockMode.READ_UNCOMMITTED); + if (status == OperationStatus.SUCCESS) + { + byte[] dataAsBytes = contentTupleBinding.entryToObject(value); + int size = dataAsBytes.length; + if (offset > size) + { + throw new RuntimeException("Offset " + offset + " is greater than message size " + size + + " for message id " + messageId + "!"); + + } + + written = size - offset; + if(written > dst.remaining()) + { + written = dst.remaining(); + } + + dst.put(dataAsBytes, offset, written); + } + return written; + } + catch (DatabaseException e) + { + throw _environmentFacade.handleDatabaseException("Error getting AMQMessage with id " + messageId + " to database: " + e.getMessage(), e); + } + } + + @Override + public boolean isPersistent() + { + return true; + } + + @Override + @SuppressWarnings("unchecked") + public <T extends StorableMessageMetaData> StoredMessage<T> addMessage(T metaData) + { + if(metaData.isPersistent()) + { + return (StoredMessage<T>) new StoredBDBMessage(getNewMessageId(), metaData); + } + else + { + return new StoredMemoryMessage(getNewMessageId(), metaData); + } + } + + /** + * Makes the specified configured object persistent. + * + * @param configuredObject Details of the configured object to store. + * @throws StoreException If the operation fails for any reason. + */ + private void storeConfiguredObjectEntry(ConfiguredObjectRecord configuredObject) throws StoreException + { + if (_stateManager.isInState(State.ACTIVE)) + { + LOGGER.debug("Storing configured object: " + configuredObject); + DatabaseEntry key = new DatabaseEntry(); + UUIDTupleBinding keyBinding = UUIDTupleBinding.getInstance(); + keyBinding.objectToEntry(configuredObject.getId(), key); + + DatabaseEntry value = new DatabaseEntry(); + ConfiguredObjectBinding queueBinding = ConfiguredObjectBinding.getInstance(); + + queueBinding.objectToEntry(configuredObject, value); + try + { + OperationStatus status = getConfiguredObjectsDb().put(null, key, value); + if (status != OperationStatus.SUCCESS) + { + throw new StoreException("Error writing configured object " + configuredObject + " to database: " + + status); + } + } + catch (DatabaseException e) + { + throw _environmentFacade.handleDatabaseException("Error writing configured object " + configuredObject + + " to database: " + e.getMessage(), e); + } + } + } + + private OperationStatus removeConfiguredObject(Transaction tx, UUID id) throws StoreException + { + + LOGGER.debug("Removing configured object: " + id); + DatabaseEntry key = new DatabaseEntry(); + UUIDTupleBinding uuidBinding = UUIDTupleBinding.getInstance(); + uuidBinding.objectToEntry(id, key); + try + { + return getConfiguredObjectsDb().delete(tx, key); + } + catch (DatabaseException e) + { + throw _environmentFacade.handleDatabaseException("Error deleting of configured object with id " + id + " from database", e); + } + } + + + + private class StoredBDBMessage implements StoredMessage<StorableMessageMetaData> + { + + private final long _messageId; + private final boolean _isRecovered; + + private StorableMessageMetaData _metaData; + private volatile SoftReference<StorableMessageMetaData> _metaDataRef; + + private byte[] _data; + private volatile SoftReference<byte[]> _dataRef; + + StoredBDBMessage(long messageId, StorableMessageMetaData metaData) + { + this(messageId, metaData, false); + } + + StoredBDBMessage(long messageId, StorableMessageMetaData metaData, boolean isRecovered) + { + _messageId = messageId; + _isRecovered = isRecovered; + + if(!_isRecovered) + { + _metaData = metaData; + } + _metaDataRef = new SoftReference<StorableMessageMetaData>(metaData); + } + + public StorableMessageMetaData getMetaData() + { + StorableMessageMetaData metaData = _metaDataRef.get(); + if(metaData == null) + { + metaData = BDBMessageStore.this.getMessageMetaData(_messageId); + _metaDataRef = new SoftReference<StorableMessageMetaData>(metaData); + } + + return metaData; + } + + public long getMessageNumber() + { + return _messageId; + } + + public void addContent(int offsetInMessage, java.nio.ByteBuffer src) + { + src = src.slice(); + + if(_data == null) + { + _data = new byte[src.remaining()]; + _dataRef = new SoftReference<byte[]>(_data); + src.duplicate().get(_data); + } + else + { + byte[] oldData = _data; + _data = new byte[oldData.length + src.remaining()]; + _dataRef = new SoftReference<byte[]>(_data); + + System.arraycopy(oldData,0,_data,0,oldData.length); + src.duplicate().get(_data, oldData.length, src.remaining()); + } + + } + + public int getContent(int offsetInMessage, java.nio.ByteBuffer dst) + { + byte[] data = _dataRef == null ? null : _dataRef.get(); + if(data != null) + { + int length = Math.min(dst.remaining(), data.length - offsetInMessage); + dst.put(data, offsetInMessage, length); + return length; + } + else + { + return BDBMessageStore.this.getContent(_messageId, offsetInMessage, dst); + } + } + + public ByteBuffer getContent(int offsetInMessage, int size) + { + byte[] data = _dataRef == null ? null : _dataRef.get(); + if(data != null) + { + return ByteBuffer.wrap(data,offsetInMessage,size); + } + else + { + ByteBuffer buf = ByteBuffer.allocate(size); + int length = getContent(offsetInMessage, buf); + buf.limit(length); + buf.position(0); + return buf; + } + } + + synchronized void store(com.sleepycat.je.Transaction txn) + { + if (!stored()) + { + try + { + _dataRef = new SoftReference<byte[]>(_data); + BDBMessageStore.this.storeMetaData(txn, _messageId, _metaData); + BDBMessageStore.this.addContent(txn, _messageId, 0, + _data == null ? ByteBuffer.allocate(0) : ByteBuffer.wrap(_data)); + } + finally + { + _metaData = null; + _data = null; + } + } + } + + public synchronized StoreFuture flushToStore() + { + if(!stored()) + { + com.sleepycat.je.Transaction txn; + try + { + txn = _environmentFacade.getEnvironment().beginTransaction( + null, null); + } + catch (DatabaseException e) + { + throw _environmentFacade.handleDatabaseException("failed to begin transaction", e); + } + store(txn); + _environmentFacade.commit(txn); + _committer.commit(txn, true); + + storedSizeChangeOccured(getMetaData().getContentSize()); + } + return StoreFuture.IMMEDIATE_FUTURE; + } + + public void remove() + { + int delta = getMetaData().getContentSize(); + BDBMessageStore.this.removeMessage(_messageId, false); + storedSizeChangeOccured(-delta); + } + + private boolean stored() + { + return _metaData == null || _isRecovered; + } + } + + private class BDBTransaction implements org.apache.qpid.server.store.Transaction + { + private com.sleepycat.je.Transaction _txn; + private int _storeSizeIncrease; + + private BDBTransaction() throws StoreException + { + try + { + _txn = _environmentFacade.getEnvironment().beginTransaction(null, null); + } + catch(DatabaseException e) + { + throw _environmentFacade.handleDatabaseException("Cannot create store transaction", e); + } + } + + public void enqueueMessage(TransactionLogResource queue, EnqueueableMessage message) throws StoreException + { + if(message.getStoredMessage() instanceof StoredBDBMessage) + { + final StoredBDBMessage storedMessage = (StoredBDBMessage) message.getStoredMessage(); + storedMessage.store(_txn); + _storeSizeIncrease += storedMessage.getMetaData().getContentSize(); + } + + BDBMessageStore.this.enqueueMessage(_txn, queue, message.getMessageNumber()); + } + + public void dequeueMessage(TransactionLogResource queue, EnqueueableMessage message) throws StoreException + { + BDBMessageStore.this.dequeueMessage(_txn, queue, message.getMessageNumber()); + } + + public void commitTran() throws StoreException + { + BDBMessageStore.this.commitTranImpl(_txn, true); + BDBMessageStore.this.storedSizeChangeOccured(_storeSizeIncrease); + } + + public StoreFuture commitTranAsync() throws StoreException + { + BDBMessageStore.this.storedSizeChangeOccured(_storeSizeIncrease); + return BDBMessageStore.this.commitTranImpl(_txn, false); + } + + public void abortTran() throws StoreException + { + BDBMessageStore.this.abortTran(_txn); + } + + public void removeXid(long format, byte[] globalId, byte[] branchId) throws StoreException + { + BDBMessageStore.this.removeXid(_txn, format, globalId, branchId); + } + + public void recordXid(long format, byte[] globalId, byte[] branchId, Record[] enqueues, + Record[] dequeues) throws StoreException + { + BDBMessageStore.this.recordXid(_txn, format, globalId, branchId, enqueues, dequeues); + } + } + + private void storedSizeChangeOccured(final int delta) throws StoreException + { + try + { + storedSizeChange(delta); + } + catch(DatabaseException e) + { + throw _environmentFacade.handleDatabaseException("Stored size change exception", e); + } + } + + private void storedSizeChange(final int delta) + { + if(getPersistentSizeHighThreshold() > 0) + { + synchronized (this) + { + // the delta supplied is an approximation of a store size change. we don;t want to check the statistic every + // time, so we do so only when there's been enough change that it is worth looking again. We do this by + // assuming the total size will change by less than twice the amount of the message data change. + long newSize = _totalStoreSize += 2*delta; + + if(!_limitBusted && newSize > getPersistentSizeHighThreshold()) + { + _totalStoreSize = getSizeOnDisk(); + + if(_totalStoreSize > getPersistentSizeHighThreshold()) + { + _limitBusted = true; + _eventManager.notifyEvent(Event.PERSISTENT_MESSAGE_SIZE_OVERFULL); + } + } + else if(_limitBusted && newSize < getPersistentSizeLowThreshold()) + { + long oldSize = _totalStoreSize; + _totalStoreSize = getSizeOnDisk(); + + if(oldSize <= _totalStoreSize) + { + + reduceSizeOnDisk(); + + _totalStoreSize = getSizeOnDisk(); + + } + + if(_totalStoreSize < getPersistentSizeLowThreshold()) + { + _limitBusted = false; + _eventManager.notifyEvent(Event.PERSISTENT_MESSAGE_SIZE_UNDERFULL); + } + + + } + } + } + } + + private void reduceSizeOnDisk() + { + _environmentFacade.getEnvironment().getConfig().setConfigParam(EnvironmentConfig.ENV_RUN_CLEANER, "false"); + boolean cleaned = false; + while (_environmentFacade.getEnvironment().cleanLog() > 0) + { + cleaned = true; + } + if (cleaned) + { + CheckpointConfig force = new CheckpointConfig(); + force.setForce(true); + _environmentFacade.getEnvironment().checkpoint(force); + } + + + _environmentFacade.getEnvironment().getConfig().setConfigParam(EnvironmentConfig.ENV_RUN_CLEANER, "true"); + } + + private long getSizeOnDisk() + { + return _environmentFacade.getEnvironment().getStats(null).getTotalLogSize(); + } + + private long getPersistentSizeLowThreshold() + { + return _persistentSizeLowThreshold; + } + + private long getPersistentSizeHighThreshold() + { + return _persistentSizeHighThreshold; + } + + + @Override + public void onDelete() + { + String storeLocation = getStoreLocation(); + + if (storeLocation != null) + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Deleting store " + storeLocation); + } + + File location = new File(storeLocation); + if (location.exists()) + { + if (!FileUtils.delete(location, true)) + { + LOGGER.error("Cannot delete " + storeLocation); + } + } + } } @Override public String getStoreType() { - return TYPE; + return _type; + } + + private Database getMessageContentDb() + { + return _environmentFacade.getOpenDatabase(MESSAGE_CONTENT_DB_NAME); + } + + private Database getConfiguredObjectsDb() + { + return _environmentFacade.getOpenDatabase(CONFIGURED_OBJECTS_DB_NAME); + } + + private Database getConfigVersionDb() + { + return _environmentFacade.getOpenDatabase(CONFIG_VERSION_DB_NAME); + } + + private Database getMessageMetaDataDb() + { + return _environmentFacade.getOpenDatabase(MESSAGE_META_DATA_DB_NAME); + } + + private Database getDeliveryDb() + { + return _environmentFacade.getOpenDatabase(DELIVERY_DB_NAME); + } + + private Database getXidDb() + { + return _environmentFacade.getOpenDatabase(XID_DB_NAME); } } diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreFactory.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreFactory.java index d7c8b23d39..ef749f2472 100644 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreFactory.java +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreFactory.java @@ -20,11 +20,8 @@ */ package org.apache.qpid.server.store.berkeleydb; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; import java.util.Map; -import org.apache.commons.configuration.Configuration; + import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.plugin.DurableConfigurationStoreFactory; import org.apache.qpid.server.plugin.MessageStoreFactory; @@ -37,7 +34,7 @@ public class BDBMessageStoreFactory implements MessageStoreFactory, DurableConfi @Override public String getType() { - return BDBMessageStore.TYPE; + return StandardEnvironmentFacade.TYPE; } @Override @@ -53,53 +50,29 @@ public class BDBMessageStoreFactory implements MessageStoreFactory, DurableConfi } @Override - public Map<String, Object> convertStoreConfiguration(Configuration storeConfiguration) - { - final List<Object> argumentNames = storeConfiguration.getList("envConfig.name"); - final List<Object> argumentValues = storeConfiguration.getList("envConfig.value"); - final int initialSize = argumentNames.size(); - - final Map<String,String> attributes = new HashMap<String,String>(initialSize); - - for (int i = 0; i < argumentNames.size(); i++) - { - final String argName = argumentNames.get(i).toString(); - final String argValue = argumentValues.get(i).toString(); - - attributes.put(argName, argValue); - } - - if(initialSize != 0) - { - return Collections.singletonMap("bdbEnvironmentConfig", (Object)attributes); - } - else - { - return Collections.emptyMap(); - } - - - } - - @Override public void validateAttributes(Map<String, Object> attributes) { - if(getType().equals(attributes.get(VirtualHost.STORE_TYPE))) + @SuppressWarnings("unchecked") + Map<String, Object> messageStoreSettings = (Map<String, Object>) attributes.get(VirtualHost.MESSAGE_STORE_SETTINGS); + if(messageStoreSettings != null && getType().equals(messageStoreSettings.get(MessageStore.STORE_TYPE))) { - Object storePath = attributes.get(VirtualHost.STORE_PATH); + Object storePath = messageStoreSettings.get(MessageStore.STORE_PATH); if(!(storePath instanceof String)) { - throw new IllegalArgumentException("Attribute '"+ VirtualHost.STORE_PATH + throw new IllegalArgumentException("Setting '"+ MessageStore.STORE_PATH +"' is required and must be of type String."); } } - if(getType().equals(attributes.get(VirtualHost.CONFIG_STORE_TYPE))) + + @SuppressWarnings("unchecked") + Map<String, Object> configurationStoreSettings = (Map<String, Object>) attributes.get(VirtualHost.CONFIGURATION_STORE_SETTINGS); + if(configurationStoreSettings != null && getType().equals(configurationStoreSettings.get(DurableConfigurationStore.STORE_TYPE))) { - Object storePath = attributes.get(VirtualHost.CONFIG_STORE_PATH); + Object storePath = configurationStoreSettings.get(DurableConfigurationStore.STORE_PATH); if(!(storePath instanceof String)) { - throw new IllegalArgumentException("Attribute '"+ VirtualHost.CONFIG_STORE_PATH + throw new IllegalArgumentException("Setting '"+ DurableConfigurationStore.STORE_PATH +"' is required and must be of type String."); } diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CoalescingCommiter.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CoalescingCommiter.java new file mode 100644 index 0000000000..a137e38baf --- /dev/null +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CoalescingCommiter.java @@ -0,0 +1,313 @@ +/* + * + * 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 java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.log4j.Logger; +import org.apache.qpid.server.store.StoreFuture; + +import com.sleepycat.je.DatabaseException; +import com.sleepycat.je.Environment; +import com.sleepycat.je.Transaction; + +public class CoalescingCommiter implements Committer +{ + private final CommitThread _commitThread; + + public CoalescingCommiter(String name, EnvironmentFacade environmentFacade) + { + _commitThread = new CommitThread("Commit-Thread-" + name, environmentFacade); + } + + @Override + public void start() + { + _commitThread.start(); + } + + @Override + public void stop() + { + _commitThread.close(); + try + { + _commitThread.join(); + } + catch (InterruptedException ie) + { + Thread.currentThread().interrupt(); + throw new RuntimeException("Commit thread has not shutdown", ie); + } + } + + @Override + public StoreFuture commit(Transaction tx, boolean syncCommit) + { + BDBCommitFuture commitFuture = new BDBCommitFuture(_commitThread, tx, syncCommit); + commitFuture.commit(); + return commitFuture; + } + + private static final class BDBCommitFuture implements StoreFuture + { + private static final Logger LOGGER = Logger.getLogger(BDBCommitFuture.class); + + private final CommitThread _commitThread; + private final Transaction _tx; + private final boolean _syncCommit; + private RuntimeException _databaseException; + private boolean _complete; + + public BDBCommitFuture(CommitThread commitThread, Transaction tx, boolean syncCommit) + { + _commitThread = commitThread; + _tx = tx; + _syncCommit = syncCommit; + } + + public synchronized void complete() + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("complete() called for transaction " + _tx); + } + _complete = true; + + notifyAll(); + } + + public synchronized void abort(RuntimeException databaseException) + { + _complete = true; + _databaseException = databaseException; + + notifyAll(); + } + + public void commit() throws DatabaseException + { + _commitThread.addJob(this, _syncCommit); + + if(!_syncCommit) + { + if(LOGGER.isDebugEnabled()) + { + LOGGER.debug("CommitAsync was requested, returning immediately."); + } + return; + } + + waitForCompletion(); + + if (_databaseException != null) + { + throw _databaseException; + } + + } + + public synchronized boolean isComplete() + { + return _complete; + } + + public synchronized void waitForCompletion() + { + long startTime = 0; + if(LOGGER.isDebugEnabled()) + { + startTime = System.currentTimeMillis(); + } + + while (!isComplete()) + { + _commitThread.explicitNotify(); + try + { + wait(250); + } + catch (InterruptedException e) + { + throw new RuntimeException(e); + } + } + + if(LOGGER.isDebugEnabled()) + { + long duration = System.currentTimeMillis() - startTime; + LOGGER.debug("waitForCompletion returning after " + duration + " ms for transaction " + _tx); + } + } + } + + /** + * Implements a thread which batches and commits a queue of {@link BDBCommitFuture} operations. The commit operations + * themselves are responsible for adding themselves to the queue and waiting for the commit to happen before + * continuing, but it is the responsibility of this thread to tell the commit operations when they have been + * completed by calling back on their {@link BDBCommitFuture#complete()} and {@link BDBCommitFuture#abort} methods. + * + * <p/><table id="crc"><caption>CRC Card</caption> <tr><th> Responsibilities <th> Collaborations </table> + */ + private static class CommitThread extends Thread + { + private static final Logger LOGGER = Logger.getLogger(CommitThread.class); + + private final AtomicBoolean _stopped = new AtomicBoolean(false); + private final Queue<BDBCommitFuture> _jobQueue = new ConcurrentLinkedQueue<BDBCommitFuture>(); + private final Object _lock = new Object(); + private final EnvironmentFacade _environmentFacade; + + public CommitThread(String name, EnvironmentFacade environmentFacade) + { + super(name); + _environmentFacade = environmentFacade; + } + + public void explicitNotify() + { + synchronized (_lock) + { + _lock.notify(); + } + } + + public void run() + { + while (!_stopped.get()) + { + synchronized (_lock) + { + while (!_stopped.get() && !hasJobs()) + { + try + { + // Periodically wake up and check, just in case we + // missed a notification. Don't want to lock the broker hard. + _lock.wait(1000); + } + catch (InterruptedException e) + { + } + } + } + processJobs(); + } + } + + private void processJobs() + { + int size = _jobQueue.size(); + + try + { + long startTime = 0; + if(LOGGER.isDebugEnabled()) + { + startTime = System.currentTimeMillis(); + } + + Environment environment = _environmentFacade.getEnvironment(); + if (environment != null && environment.isValid()) + { + environment.flushLog(true); + } + + if(LOGGER.isDebugEnabled()) + { + long duration = System.currentTimeMillis() - startTime; + LOGGER.debug("flushLog completed in " + duration + " ms"); + } + + for(int i = 0; i < size; i++) + { + BDBCommitFuture commit = _jobQueue.poll(); + commit.complete(); + } + + } + catch (DatabaseException e) + { + try + { + LOGGER.error("Exception during environment log flush", e); + + for(int i = 0; i < size; i++) + { + BDBCommitFuture commit = _jobQueue.poll(); + commit.abort(e); + } + } + finally + { + LOGGER.error("Closing store environment", e); + + try + { + _environmentFacade.close(); + } + catch (DatabaseException ex) + { + LOGGER.error("Exception closing store environment", ex); + } + } + } + } + + private boolean hasJobs() + { + return !_jobQueue.isEmpty(); + } + + public void addJob(BDBCommitFuture commit, final boolean sync) + { + if (_stopped.get()) + { + throw new IllegalStateException("Commit thread is stopped"); + } + _jobQueue.add(commit); + if(sync) + { + synchronized (_lock) + { + _lock.notifyAll(); + } + } + } + + public void close() + { + RuntimeException e = new RuntimeException("Commit thread has been closed, transaction aborted"); + synchronized (_lock) + { + _stopped.set(true); + BDBCommitFuture commit = null; + while ((commit = _jobQueue.poll()) != null) + { + commit.abort(e); + } + _lock.notifyAll(); + } + } + } +} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/MessageStoreCreatorTest.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/Committer.java index 730001d849..36ee2ad306 100644 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/MessageStoreCreatorTest.java +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/Committer.java @@ -20,22 +20,36 @@ */ package org.apache.qpid.server.store.berkeleydb; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.MessageStoreCreator; -import org.apache.qpid.server.store.berkeleydb.BDBMessageStore; -import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.server.store.StoreFuture; -public class MessageStoreCreatorTest extends QpidTestCase +import com.sleepycat.je.Transaction; + +public interface Committer { - private static final String[] STORE_TYPES = {BDBMessageStore.TYPE}; + void start(); + + StoreFuture commit(Transaction tx, boolean syncCommit); + + void stop(); - public void testMessageStoreCreator() + Committer IMMEDIATE_FUTURE_COMMITTER = new Committer() { - MessageStoreCreator messageStoreCreator = new MessageStoreCreator(); - for (String type : STORE_TYPES) + + @Override + public void start() { - MessageStore store = messageStoreCreator.createMessageStore(type); - assertNotNull("Store of type " + type + " is not created", store); } - } -} + + @Override + public StoreFuture commit(Transaction tx, boolean syncCommit) + { + return StoreFuture.IMMEDIATE_FUTURE; + } + + @Override + public void stop() + { + } + }; + +}
\ No newline at end of file diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvironmentFacade.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvironmentFacade.java new file mode 100644 index 0000000000..144ab83238 --- /dev/null +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvironmentFacade.java @@ -0,0 +1,58 @@ +/* + * + * 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 java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import com.sleepycat.je.Database; +import com.sleepycat.je.DatabaseConfig; +import com.sleepycat.je.DatabaseException; +import com.sleepycat.je.Environment; +import com.sleepycat.je.EnvironmentConfig; + +public interface EnvironmentFacade +{ + @SuppressWarnings("serial") + final Map<String, String> ENVCONFIG_DEFAULTS = Collections.unmodifiableMap(new HashMap<String, String>() + {{ + put(EnvironmentConfig.LOCK_N_LOCK_TABLES, "7"); + // Turn off stats generation - feature introduced (and on by default) from BDB JE 5.0.84 + put(EnvironmentConfig.STATS_COLLECT, "false"); + }}); + + Environment getEnvironment(); + + Committer createCommitter(String name); + + void openDatabases(DatabaseConfig dbConfig, String... databaseNames); + + Database getOpenDatabase(String name); + + void commit(com.sleepycat.je.Transaction tx); + + DatabaseException handleDatabaseException(String contextMessage, DatabaseException e); + + String getStoreLocation(); + + void close(); +} diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/HAMessageStore.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvironmentFacadeFactory.java index 59483751ca..d242790efb 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/HAMessageStore.java +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvironmentFacadeFactory.java @@ -1,4 +1,5 @@ /* + * * 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 @@ -17,13 +18,16 @@ * under the License. * */ -package org.apache.qpid.server.store; +package org.apache.qpid.server.store.berkeleydb; + +import org.apache.qpid.server.model.VirtualHost; -public interface HAMessageStore extends MessageStore +public interface EnvironmentFacadeFactory { - /** - * Used to indicate that a store requires to make itself unavailable for read and read/write - * operations. - */ - void passivate(); + public static final String ENVIRONMENT_CONFIGURATION = "bdbEnvironmentConfig"; + + EnvironmentFacade createEnvironmentFacade(VirtualHost<?> virtualHost, boolean isMessageStore); + + String getType(); + } diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/LoggingAsyncExceptionListener.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/LoggingAsyncExceptionListener.java new file mode 100644 index 0000000000..b13766a136 --- /dev/null +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/LoggingAsyncExceptionListener.java @@ -0,0 +1,37 @@ +/* + * + * 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.log4j.Logger; + +import com.sleepycat.je.ExceptionEvent; +import com.sleepycat.je.ExceptionListener; + +public class LoggingAsyncExceptionListener implements ExceptionListener +{ + private static final Logger LOGGER = Logger.getLogger(LoggingAsyncExceptionListener.class); + + @Override + public void exceptionThrown(ExceptionEvent event) + { + LOGGER.error("Asynchronous exception thrown by BDB thread '" + event.getThreadName() + "'", event.getException()); + } +}
\ No newline at end of file diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacade.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacade.java new file mode 100644 index 0000000000..8117ca1a9a --- /dev/null +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacade.java @@ -0,0 +1,228 @@ +/* + * + * 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 java.io.File; +import java.util.HashMap; +import java.util.Map; + +import org.apache.log4j.Logger; + +import com.sleepycat.je.Database; +import com.sleepycat.je.DatabaseConfig; +import com.sleepycat.je.DatabaseException; +import com.sleepycat.je.Environment; +import com.sleepycat.je.EnvironmentConfig; + +public class StandardEnvironmentFacade implements EnvironmentFacade +{ + private static final Logger LOGGER = Logger.getLogger(StandardEnvironmentFacade.class); + public static final String TYPE = "BDB"; + + private final String _storePath; + private final Map<String, Database> _databases = new HashMap<String, Database>(); + + private Environment _environment; + + public StandardEnvironmentFacade(String storePath, Map<String, String> attributes) + { + _storePath = storePath; + + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("Creating environment at environment path " + _storePath); + } + + File environmentPath = new File(storePath); + if (!environmentPath.exists()) + { + if (!environmentPath.mkdirs()) + { + throw new IllegalArgumentException("Environment path " + environmentPath + " could not be read or created. " + + "Ensure the path is correct and that the permissions are correct."); + } + } + + EnvironmentConfig envConfig = new EnvironmentConfig(); + envConfig.setAllowCreate(true); + envConfig.setTransactional(true); + + for (Map.Entry<String, String> configItem : attributes.entrySet()) + { + LOGGER.debug("Setting EnvironmentConfig key " + configItem.getKey() + " to '" + configItem.getValue() + "'"); + envConfig.setConfigParam(configItem.getKey(), configItem.getValue()); + } + + envConfig.setExceptionListener(new LoggingAsyncExceptionListener()); + + _environment = new Environment(environmentPath, envConfig); + } + + @Override + public void commit(com.sleepycat.je.Transaction tx) + { + try + { + tx.commitNoSync(); + } + catch (DatabaseException de) + { + LOGGER.error("Got DatabaseException on commit, closing environment", de); + + closeEnvironmentSafely(); + + throw handleDatabaseException("Got DatabaseException on commit", de); + } + } + + @Override + public void close() + { + closeDatabases(); + closeEnvironment(); + } + + private void closeDatabases() + { + RuntimeException firstThrownException = null; + for (Database database : _databases.values()) + { + try + { + database.close(); + } + catch(RuntimeException e) + { + if (firstThrownException == null) + { + firstThrownException = e; + } + } + } + if (firstThrownException != null) + { + throw firstThrownException; + } + } + + private void closeEnvironmentSafely() + { + if (_environment != null) + { + if (_environment.isValid()) + { + try + { + closeDatabases(); + } + catch(Exception e) + { + LOGGER.error("Exception closing environment databases", e); + } + } + try + { + _environment.close(); + } + catch (DatabaseException ex) + { + LOGGER.error("Exception closing store environment", ex); + } + catch (IllegalStateException ex) + { + LOGGER.error("Exception closing store environment", ex); + } + finally + { + _environment = null; + } + } + } + + @Override + public Environment getEnvironment() + { + return _environment; + } + + private void closeEnvironment() + { + if (_environment != null) + { + // Clean the log before closing. This makes sure it doesn't contain + // redundant data. Closing without doing this means the cleaner may + // not get a chance to finish. + try + { + _environment.cleanLog(); + } + finally + { + _environment.close(); + _environment = null; + } + } + } + + @Override + public DatabaseException handleDatabaseException(String contextMessage, DatabaseException e) + { + if (_environment != null && !_environment.isValid()) + { + closeEnvironmentSafely(); + } + return e; + } + + @Override + public void openDatabases(DatabaseConfig dbConfig, String... databaseNames) + { + for (String databaseName : databaseNames) + { + Database database = _environment.openDatabase(null, databaseName, dbConfig); + _databases .put(databaseName, database); + } + } + + @Override + public Database getOpenDatabase(String name) + { + Database database = _databases.get(name); + if (database == null) + { + throw new IllegalArgumentException("Database with name '" + name + "' has not been opened"); + } + return database; + } + + @Override + public Committer createCommitter(String name) + { + return new CoalescingCommiter(name, this); + } + + @Override + public String getStoreLocation() + { + return _storePath; + } + +} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacadeFactory.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacadeFactory.java new file mode 100644 index 0000000000..75e14a70c7 --- /dev/null +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacadeFactory.java @@ -0,0 +1,83 @@ +/* + * + * 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 java.io.File; +import java.util.HashMap; +import java.util.Map; + +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.store.DurableConfigurationStore; +import org.apache.qpid.server.store.MessageStore; + +public class StandardEnvironmentFacadeFactory implements EnvironmentFacadeFactory +{ + + @SuppressWarnings("unchecked") + @Override + public EnvironmentFacade createEnvironmentFacade(VirtualHost<?> virtualHost, boolean isMessageStore) + { + String name = virtualHost.getName(); + Map<String, Object> messageStoreSettings = virtualHost.getMessageStoreSettings(); + Map<String, String> envConfigMap = new HashMap<String, String>(); + envConfigMap.putAll(EnvironmentFacade.ENVCONFIG_DEFAULTS); + + final String defaultPath = System.getProperty(BrokerProperties.PROPERTY_QPID_WORK) + File.separator + "bdbstore" + File.separator + name; + + String storeLocation; + if(isMessageStore) + { + Object environmentConfigurationAttributes = messageStoreSettings.get(ENVIRONMENT_CONFIGURATION); + if (environmentConfigurationAttributes instanceof Map) + { + envConfigMap.putAll((Map<String, String>) environmentConfigurationAttributes); + } + + storeLocation = (String) messageStoreSettings.get(MessageStore.STORE_PATH); + } + else // we are acting only as the durable config store + { + Map<String, Object> configurationStoreSettings = virtualHost.getConfigurationStoreSettings(); + + Object environmentConfigurationAttributes = configurationStoreSettings.get(ENVIRONMENT_CONFIGURATION); + if (environmentConfigurationAttributes instanceof Map) + { + envConfigMap.putAll((Map<String, String>) environmentConfigurationAttributes); + } + + storeLocation = (String) configurationStoreSettings.get(DurableConfigurationStore.STORE_PATH); + } + if(storeLocation == null) + { + storeLocation = defaultPath; + } + + return new StandardEnvironmentFacade(storeLocation, envConfigMap); + } + + @Override + public String getType() + { + return StandardEnvironmentFacade.TYPE; + } + +} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/DatabasePinger.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/DatabasePinger.java new file mode 100644 index 0000000000..38fdf34196 --- /dev/null +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/DatabasePinger.java @@ -0,0 +1,76 @@ +/* + * + * 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.replication; + +import org.apache.qpid.server.store.berkeleydb.EnvironmentFacade; + +import com.sleepycat.bind.tuple.IntegerBinding; +import com.sleepycat.bind.tuple.LongBinding; +import com.sleepycat.je.Database; +import com.sleepycat.je.DatabaseEntry; +import com.sleepycat.je.DatabaseException; +import com.sleepycat.je.Transaction; + +public class DatabasePinger +{ + public static final String PING_DATABASE_NAME = "PINGDB"; + private static final int ID = 0; + + public void pingDb(EnvironmentFacade facade) + { + try + { + final Database db = facade.getOpenDatabase(PING_DATABASE_NAME); + + DatabaseEntry key = new DatabaseEntry(); + IntegerBinding.intToEntry(ID, key); + + DatabaseEntry value = new DatabaseEntry(); + LongBinding.longToEntry(System.currentTimeMillis(), value); + Transaction txn = null; + try + { + txn = facade.getEnvironment().beginTransaction(null, null); + db.put(txn, key, value); + txn.commit(); + txn = null; + } + finally + { + try + { + if (txn != null) + { + txn.abort(); + } + } + finally + { + db.close(); + } + } + } + catch (DatabaseException de) + { + facade.handleDatabaseException("DatabaseException from DatabasePinger ", de); + } + } +} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentConfiguration.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentConfiguration.java new file mode 100644 index 0000000000..76a48c189e --- /dev/null +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentConfiguration.java @@ -0,0 +1,40 @@ +/* + * + * 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.replication; + +import java.util.Map; + +public interface ReplicatedEnvironmentConfiguration +{ + String getName(); + String getGroupName(); + String getHostPort(); + String getHelperHostPort(); + String getDurability(); + boolean isCoalescingSync(); + boolean isDesignatedPrimary(); + int getPriority(); + int getQuorumOverride(); + String getStorePath(); + Map<String, String> getParameters(); + Map<String, String> getReplicationParameters(); +} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java new file mode 100644 index 0000000000..3e15e9bdcc --- /dev/null +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java @@ -0,0 +1,1083 @@ +/* + * + * 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.replication; + +import java.io.File; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.util.ArrayList; +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.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicReference; + +import org.apache.log4j.Logger; +import org.apache.qpid.server.store.berkeleydb.CoalescingCommiter; +import org.apache.qpid.server.store.berkeleydb.Committer; +import org.apache.qpid.server.store.berkeleydb.EnvironmentFacade; +import org.apache.qpid.server.store.berkeleydb.LoggingAsyncExceptionListener; +import org.apache.qpid.server.util.DaemonThreadFactory; + +import com.sleepycat.je.Database; +import com.sleepycat.je.DatabaseConfig; +import com.sleepycat.je.DatabaseException; +import com.sleepycat.je.Durability; +import com.sleepycat.je.Environment; +import com.sleepycat.je.EnvironmentConfig; +import com.sleepycat.je.EnvironmentFailureException; +import com.sleepycat.je.Transaction; +import com.sleepycat.je.rep.InsufficientLogException; +import com.sleepycat.je.rep.InsufficientReplicasException; +import com.sleepycat.je.rep.NetworkRestore; +import com.sleepycat.je.rep.NetworkRestoreConfig; +import com.sleepycat.je.rep.NodeState; +import com.sleepycat.je.rep.RepInternal; +import com.sleepycat.je.rep.ReplicatedEnvironment; +import com.sleepycat.je.rep.ReplicationConfig; +import com.sleepycat.je.rep.ReplicationMutableConfig; +import com.sleepycat.je.rep.ReplicationNode; +import com.sleepycat.je.rep.RestartRequiredException; +import com.sleepycat.je.rep.StateChangeEvent; +import com.sleepycat.je.rep.StateChangeListener; +import com.sleepycat.je.rep.util.DbPing; +import com.sleepycat.je.rep.util.ReplicationGroupAdmin; +import com.sleepycat.je.rep.utilint.ServiceDispatcher.ServiceConnectFailedException; +import com.sleepycat.je.rep.vlsn.VLSNRange; +import com.sleepycat.je.utilint.PropUtil; +import com.sleepycat.je.utilint.VLSN; + +public class ReplicatedEnvironmentFacade implements EnvironmentFacade, StateChangeListener +{ + public static final String DB_PING_SOCKET_TIMEOUT_PROPERTY_NAME = "qpid.bdb.ha.db_ping_socket_timeout"; + public static final String REMOTE_NODE_MONITOR_INTERVAL_PROPERTY_NAME = "qpid.bdb.ha.remote_node_monitor_interval"; + + private static final Logger LOGGER = Logger.getLogger(ReplicatedEnvironmentFacade.class); + + private static final int DEFAULT_DB_PING_SOCKET_TIMEOUT = 1000; + private static final int DEFAULT_REMOTE_NODE_MONITOR_INTERVAL = 1000; + + private static final int DB_PING_SOCKET_TIMEOUT = Integer.getInteger(DB_PING_SOCKET_TIMEOUT_PROPERTY_NAME, DEFAULT_DB_PING_SOCKET_TIMEOUT); + private static final int REMOTE_NODE_MONITOR_INTERVAL = Integer.getInteger(REMOTE_NODE_MONITOR_INTERVAL_PROPERTY_NAME, DEFAULT_REMOTE_NODE_MONITOR_INTERVAL); + + @SuppressWarnings("serial") + private static final Map<String, String> REPCONFIG_DEFAULTS = Collections.unmodifiableMap(new HashMap<String, String>() + {{ + /** + * Parameter decreased as the 24h default may lead very large log files for most users. + */ + put(ReplicationConfig.REP_STREAM_TIMEOUT, "1 h"); + /** + * Parameter increased as the 5 s default may lead to spurious timeouts. + */ + put(ReplicationConfig.REPLICA_ACK_TIMEOUT, "15 s"); + /** + * Parameter increased as the 10 s default may lead to spurious timeouts. + */ + put(ReplicationConfig.INSUFFICIENT_REPLICAS_TIMEOUT, "20 s"); + /** + * Parameter decreased as the 10 h default may cause user confusion. + */ + put(ReplicationConfig.ENV_SETUP_TIMEOUT, "15 min"); + /** + * Parameter changed from default (off) to allow the Environment to start in the + * UNKNOWN state when the majority is not available. + */ + put(ReplicationConfig.ENV_UNKNOWN_STATE_TIMEOUT, "5 s"); + /** + * Parameter changed from default true so we adopt immediately adopt the new behaviour early. False + * is scheduled to become default after JE 5.1. + */ + put(ReplicationConfig.PROTOCOL_OLD_STRING_ENCODING, Boolean.FALSE.toString()); + /** + * Parameter decreased as a default 5min interval may lead to bigger data losses on Node + * with NO_SYN durability in case if such Node crushes. + */ + put(ReplicationConfig.LOG_FLUSH_TASK_INTERVAL, "1 min"); + }}); + + public static final String TYPE = "BDB-HA"; + + // TODO: JMX will change to observe the model, at that point these names will disappear + public static final String GRP_MEM_COL_NODE_HOST_PORT = "NodeHostPort"; + public static final String GRP_MEM_COL_NODE_NAME = "NodeName"; + + private final ReplicatedEnvironmentConfiguration _configuration; + private final Durability _durability; + private final Boolean _coalescingSync; + private final String _prettyGroupNodeName; + private final File _environmentDirectory; + + private final ExecutorService _environmentJobExecutor; + private final ScheduledExecutorService _groupChangeExecutor; + private final AtomicReference<State> _state = new AtomicReference<State>(State.OPENING); + private final ConcurrentMap<String, DatabaseHolder> _databases = new ConcurrentHashMap<String, DatabaseHolder>(); + private final AtomicReference<StateChangeListener> _stateChangeListener = new AtomicReference<StateChangeListener>(); + + private volatile ReplicatedEnvironment _environment; + private volatile long _joinTime; + private volatile ReplicatedEnvironment.State _lastKnownEnvironmentState; + + public ReplicatedEnvironmentFacade(ReplicatedEnvironmentConfiguration configuration) + { + _environmentDirectory = new File(configuration.getStorePath()); + if (!_environmentDirectory.exists()) + { + if (!_environmentDirectory.mkdirs()) + { + throw new IllegalArgumentException("Environment path " + _environmentDirectory + " could not be read or created. " + + "Ensure the path is correct and that the permissions are correct."); + } + } + + _configuration = configuration; + + _durability = Durability.parse(_configuration.getDurability()); + _coalescingSync = _configuration.isCoalescingSync(); + _prettyGroupNodeName = _configuration.getGroupName() + ":" + _configuration.getName(); + + // we relay on this executor being single-threaded as we need to restart and mutate the environment in one thread + _environmentJobExecutor = Executors.newSingleThreadExecutor(new DaemonThreadFactory("Environment-" + _prettyGroupNodeName)); + _groupChangeExecutor = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors() + 1, new DaemonThreadFactory("Group-Change-Learner:" + _prettyGroupNodeName)); + _groupChangeExecutor.schedule(new RemoteNodeStateLearner(), 100, TimeUnit.MILLISECONDS); // TODO make configurable + + // create environment in a separate thread to avoid renaming of the current thread by JE + _environment = createEnvironment(true); + } + + @Override + public void commit(final Transaction tx) + { + try + { + // Using commit() instead of commitNoSync() for the HA store to allow + // the HA durability configuration to influence resulting behaviour. + tx.commit(); + } + catch (DatabaseException de) + { + throw handleDatabaseException("Got DatabaseException on commit, closing environment", de); + } + } + + @Override + public void close() + { + if (_state.compareAndSet(State.OPENING, State.CLOSING) || + _state.compareAndSet(State.OPEN, State.CLOSING) || + _state.compareAndSet(State.RESTARTING, State.CLOSING) ) + { + try + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Closing replicated environment facade for " + _prettyGroupNodeName + " current state is " + _state.get()); + } + + shutdownAndAwaitExecutorService(_environmentJobExecutor); + shutdownAndAwaitExecutorService(_groupChangeExecutor); + + closeDatabases(); + closeEnvironment(); + } + finally + { + _state.compareAndSet(State.CLOSING, State.CLOSED); + } + } + } + + private void shutdownAndAwaitExecutorService(ExecutorService executorService) + { + executorService.shutdown(); + try + { + boolean wasShutdown = executorService.awaitTermination(5000, TimeUnit.MILLISECONDS); + if (!wasShutdown) + { + LOGGER.warn("Executor service " + executorService + " did not shutdown within allowed time period, ignoring"); + } + } + catch (InterruptedException e) + { + Thread.currentThread().interrupt(); + LOGGER.warn("Shutdown of executor service " + executorService + " was interrupted"); + } + } + + @Override + public DatabaseException handleDatabaseException(String contextMessage, final DatabaseException dbe) + { + boolean restart = (dbe instanceof InsufficientReplicasException || dbe instanceof InsufficientReplicasException || dbe instanceof RestartRequiredException); + if (restart) + { + tryToRestartEnvironment(dbe); + } + return dbe; + } + + private void tryToRestartEnvironment(final DatabaseException dbe) + { + if (_state.compareAndSet(State.OPEN, State.RESTARTING)) + { + if (dbe != null && LOGGER.isDebugEnabled()) + { + LOGGER.debug("Environment restarting due to exception " + dbe.getMessage(), dbe); + } + + _environmentJobExecutor.execute(new Runnable() + { + @Override + public void run() + { + try + { + restartEnvironment(); + } + catch (Exception e) + { + LOGGER.error("Exception on environment restart", e); + } + } + }); + + } + else + { + LOGGER.info("Cannot restart environment because of facade state: " + _state.get()); + } + } + + @Override + public void openDatabases(DatabaseConfig dbConfig, String... databaseNames) + { + if (_state.get() != State.OPEN) + { + throw new IllegalStateException("Environment facade is not in opened state"); + } + + if (!_environment.isValid()) + { + throw new IllegalStateException("Environment is not valid"); + } + + if (_environment.getState() != ReplicatedEnvironment.State.MASTER) + { + throw new IllegalStateException("Databases can only be opened on Master node"); + } + + for (String databaseName : databaseNames) + { + _databases.put(databaseName, new DatabaseHolder(dbConfig)); + } + for (String databaseName : databaseNames) + { + DatabaseHolder holder = _databases.get(databaseName); + openDatabaseInternally(databaseName, holder); + } + } + + private void openDatabaseInternally(String databaseName, DatabaseHolder holder) + { + if (_state.get() == State.OPEN) + { + Database database = _environment.openDatabase(null, databaseName, holder.getConfig()); + holder.setDatabase(database); + } + } + + @Override + public Database getOpenDatabase(String name) + { + if (_state.get() != State.OPEN) + { + throw new IllegalStateException("Environment facade is not in opened state"); + } + + if (!_environment.isValid()) + { + throw new IllegalStateException("Environment is not valid"); + } + DatabaseHolder databaseHolder = _databases.get(name); + if (databaseHolder == null) + { + throw new IllegalArgumentException("Database with name '" + name + "' has never been requested to be opened"); + } + Database database = databaseHolder.getDatabase(); + if (database == null) + { + throw new IllegalArgumentException("Database with name '" + name + "' has not been opened"); + } + return database; + } + + @Override + public String getStoreLocation() + { + return _environmentDirectory.getAbsolutePath(); + } + + @Override + public void stateChange(final StateChangeEvent stateChangeEvent) + { + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("The node '" + _prettyGroupNodeName + "' state is " + stateChangeEvent.getState()); + } + + if (_state.get() != State.CLOSING && _state.get() != State.CLOSED) + { + _groupChangeExecutor.submit(new Runnable() + { + @Override + public void run() + { + stateChanged(stateChangeEvent); + } + }); + } + else + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Ignoring the state environment change event as the environment facade for node '" + _prettyGroupNodeName + + "' is in state " + _state.get()); + } + } + } + + private void stateChanged(StateChangeEvent stateChangeEvent) + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Received BDB event, new BDB state " + stateChangeEvent.getState() + " Facade state : " + _state.get()); + } + ReplicatedEnvironment.State state = stateChangeEvent.getState(); + + if ( _state.get() != State.CLOSED && _state.get() != State.CLOSING) + { + if (state == ReplicatedEnvironment.State.REPLICA || state == ReplicatedEnvironment.State.MASTER) + { + if (_state.compareAndSet(State.OPENING, State.OPEN) || _state.compareAndSet(State.RESTARTING, State.OPEN)) + { + LOGGER.info("The environment facade is in open state for node " + _prettyGroupNodeName); + _joinTime = System.currentTimeMillis(); + } + if (state == ReplicatedEnvironment.State.MASTER) + { + reopenDatabases(); + } + } + + StateChangeListener listener = _stateChangeListener.get(); + if (listener != null && (_state.get() == State.OPEN || _state.get() == State.RESTARTING)) + { + listener.stateChange(stateChangeEvent); + } + + if (_lastKnownEnvironmentState == ReplicatedEnvironment.State.MASTER && state == ReplicatedEnvironment.State.DETACHED && _state.get() == State.OPEN) + { + tryToRestartEnvironment(null); + } + } + _lastKnownEnvironmentState = state; + } + + private void reopenDatabases() + { + if (_state.get() == State.OPEN) + { + DatabaseConfig pingDbConfig = new DatabaseConfig(); + pingDbConfig.setTransactional(true); + pingDbConfig.setAllowCreate(true); + + _databases.putIfAbsent(DatabasePinger.PING_DATABASE_NAME, new DatabaseHolder(pingDbConfig)); + + for (Map.Entry<String, DatabaseHolder> entry : _databases.entrySet()) + { + openDatabaseInternally(entry.getKey(), entry.getValue()); + } + } + } + + public String getGroupName() + { + return (String)_configuration.getGroupName(); + } + + public String getNodeName() + { + return _configuration.getName(); + } + + public String getHostPort() + { + return (String)_configuration.getHostPort(); + } + + public String getHelperHostPort() + { + return (String)_configuration.getHelperHostPort(); + } + + public String getDurability() + { + return _durability.toString(); + } + + public boolean isCoalescingSync() + { + return _coalescingSync; + } + + public String getNodeState() + { + if (_state.get() != State.OPEN) + { + return ReplicatedEnvironment.State.UNKNOWN.name(); + } + ReplicatedEnvironment.State state = _environment.getState(); + return state.toString(); + } + + public boolean isDesignatedPrimary() + { + if (_state.get() != State.OPEN) + { + throw new IllegalStateException("Environment facade is not opened"); + } + return _environment.getRepMutableConfig().getDesignatedPrimary(); + } + + public Future<Void> setDesignatedPrimary(final boolean isPrimary) + { + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("Submitting a job to set designated primary on " + _prettyGroupNodeName + " to " + isPrimary); + } + + return _environmentJobExecutor.submit(new Callable<Void>() + { + @Override + public Void call() + { + setDesignatedPrimaryInternal(isPrimary); + return null; + } + }); + } + + void setDesignatedPrimaryInternal(final boolean isPrimary) + { + try + { + final ReplicationMutableConfig oldConfig = _environment.getRepMutableConfig(); + final ReplicationMutableConfig newConfig = oldConfig.setDesignatedPrimary(isPrimary); + _environment.setRepMutableConfig(newConfig); + + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("Node " + _prettyGroupNodeName + " successfully set designated primary : " + isPrimary); + } + } + catch (Exception e) + { + LOGGER.error("Cannot set designated primary to " + isPrimary + " on node " + _prettyGroupNodeName, e); + } + } + + int getPriority() + { + if (_state.get() != State.OPEN) + { + throw new IllegalStateException("Environment facade is not opened"); + } + ReplicationMutableConfig repConfig = _environment.getRepMutableConfig(); + return repConfig.getNodePriority(); + } + + public Future<Void> setPriority(final int priority) + { + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("Submitting a job to set priority on " + _prettyGroupNodeName + " to " + priority); + } + + return _environmentJobExecutor.submit(new Callable<Void>() + { + @Override + public Void call() + { + setPriorityInternal(priority); + return null; + } + }); + } + + void setPriorityInternal(int priority) + { + try + { + final ReplicationMutableConfig oldConfig = _environment.getRepMutableConfig(); + final ReplicationMutableConfig newConfig = oldConfig.setNodePriority(priority); + _environment.setRepMutableConfig(newConfig); + + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Node " + _prettyGroupNodeName + " priority has been changed to " + priority); + } + } + catch (Exception e) + { + LOGGER.error("Cannot set priority to " + priority + " on node " + _prettyGroupNodeName, e); + } + } + + int getElectableGroupSizeOverride() + { + if (_state.get() != State.OPEN) + { + throw new IllegalStateException("Environment facade is not opened"); + } + ReplicationMutableConfig repConfig = _environment.getRepMutableConfig(); + return repConfig.getElectableGroupSizeOverride(); + } + + public Future<Void> setElectableGroupSizeOverride(final int electableGroupOverride) + { + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("Submitting a job to set electable group override on " + _prettyGroupNodeName + " to " + electableGroupOverride); + } + + return _environmentJobExecutor.submit(new Callable<Void>() + { + @Override + public Void call() + { + setElectableGroupSizeOverrideInternal(electableGroupOverride); + return null; + } + }); + } + + void setElectableGroupSizeOverrideInternal(int electableGroupOverride) + { + try + { + final ReplicationMutableConfig oldConfig = _environment.getRepMutableConfig(); + final ReplicationMutableConfig newConfig = oldConfig.setElectableGroupSizeOverride(electableGroupOverride); + _environment.setRepMutableConfig(newConfig); + + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Node " + _prettyGroupNodeName + " electable group size override has been changed to " + electableGroupOverride); + } + } + catch (Exception e) + { + LOGGER.error("Cannot set electable group size to " + electableGroupOverride + " on node " + _prettyGroupNodeName, e); + } + } + + + public long getJoinTime() + { + return _joinTime ; + } + + public long getLastKnownReplicationTransactionId() + { + if (_state.get() == State.OPEN) + { + VLSNRange range = RepInternal.getRepImpl(_environment).getVLSNIndex().getRange(); + VLSN lastTxnEnd = range.getLastTxnEnd(); + return lastTxnEnd.getSequence(); + } + else + { + return -1L; + } + } + + public List<Map<String, String>> getGroupMembers() + { + List<Map<String, String>> members = new ArrayList<Map<String, String>>(); + + for (ReplicationNode node : _environment.getGroup().getNodes()) + { + Map<String, String> nodeMap = new HashMap<String, String>(); + nodeMap.put(ReplicatedEnvironmentFacade.GRP_MEM_COL_NODE_NAME, node.getName()); + nodeMap.put(ReplicatedEnvironmentFacade.GRP_MEM_COL_NODE_HOST_PORT, node.getHostName() + ":" + node.getPort()); + members.add(nodeMap); + } + + return members; + } + + public void removeNodeFromGroup(final String nodeName) + { + createReplicationGroupAdmin().removeMember(nodeName); + } + + public void updateAddress(final String nodeName, final String newHostName, final int newPort) + { + createReplicationGroupAdmin().updateAddress(nodeName, newHostName, newPort); + } + + private ReplicationGroupAdmin createReplicationGroupAdmin() + { + final Set<InetSocketAddress> helpers = new HashSet<InetSocketAddress>(); + helpers.addAll(_environment.getRepConfig().getHelperSockets()); + + final ReplicationConfig repConfig = _environment.getRepConfig(); + helpers.add(InetSocketAddress.createUnresolved(repConfig.getNodeHostname(), repConfig.getNodePort())); + + return new ReplicationGroupAdmin(_configuration.getGroupName(), helpers); + } + + + public ReplicatedEnvironment getEnvironment() + { + return _environment; + } + + public State getFacadeState() + { + return _state.get(); + } + + public void setStateChangeListener(StateChangeListener stateChangeListener) + { + if (_stateChangeListener.compareAndSet(null, stateChangeListener)) + { + _environment.setStateChangeListener(this); + } + else + { + throw new IllegalStateException("StateChangeListener is already set on " + _prettyGroupNodeName); + } + } + + private void closeEnvironment() + { + // Clean the log before closing. This makes sure it doesn't contain + // redundant data. Closing without doing this means the cleaner may not + // get a chance to finish. + try + { + if (_environment.isValid()) + { + _environment.cleanLog(); + } + } + finally + { + _environment.close(); + _environment = null; + } + } + + private void restartEnvironment() + { + LOGGER.info("Restarting environment"); + + closeEnvironmentOnRestart(); + + _environment = createEnvironment(false); + + if (_stateChangeListener.get() != null) + { + _environment.setStateChangeListener(this); + } + + LOGGER.info("Environment is restarted"); + } + + private void closeEnvironmentOnRestart() + { + Environment environment = _environment; + if (environment != null) + { + try + { + if (environment.isValid()) + { + try + { + closeDatabases(); + } + catch(Exception e) + { + LOGGER.warn("Ignoring an exception whilst closing databases", e); + } + } + environment.close(); + } + catch (EnvironmentFailureException efe) + { + LOGGER.warn("Ignoring an exception whilst closing environment", efe); + } + } + } + + private void closeDatabases() + { + RuntimeException firstThrownException = null; + for (Map.Entry<String, DatabaseHolder> entry : _databases.entrySet()) + { + DatabaseHolder databaseHolder = entry.getValue(); + Database database = databaseHolder.getDatabase(); + if (database != null) + { + try + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Closing database " + entry.getKey() + " on " + _prettyGroupNodeName); + } + + database.close(); + } + catch(RuntimeException e) + { + LOGGER.error("Failed to close database on " + _prettyGroupNodeName, e); + if (firstThrownException == null) + { + firstThrownException = e; + } + } + finally + { + databaseHolder.setDatabase(null); + } + } + } + if (firstThrownException != null) + { + throw firstThrownException; + } + } + + private ReplicatedEnvironment createEnvironment(boolean createEnvironmentInSeparateThread) + { + String groupName = _configuration.getGroupName(); + String helperHostPort = _configuration.getHelperHostPort(); + String hostPort = _configuration.getHostPort(); + Map<String, String> environmentParameters = _configuration.getParameters(); + Map<String, String> replicationEnvironmentParameters = _configuration.getReplicationParameters(); + boolean designatedPrimary = _configuration.isDesignatedPrimary(); + int priority = _configuration.getPriority(); + int quorumOverride = _configuration.getQuorumOverride(); + + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("Creating environment"); + LOGGER.info("Environment path " + _environmentDirectory.getAbsolutePath()); + LOGGER.info("Group name " + groupName); + LOGGER.info("Node name " + _configuration.getName()); + LOGGER.info("Node host port " + hostPort); + LOGGER.info("Helper host port " + helperHostPort); + LOGGER.info("Durability " + _durability); + LOGGER.info("Coalescing sync " + _coalescingSync); + LOGGER.info("Designated primary (applicable to 2 node case only) " + designatedPrimary); + LOGGER.info("Node priority " + priority); + LOGGER.info("Quorum override " + quorumOverride); + } + + Map<String, String> replicationEnvironmentSettings = new HashMap<String, String>(REPCONFIG_DEFAULTS); + if (replicationEnvironmentParameters != null && !replicationEnvironmentParameters.isEmpty()) + { + replicationEnvironmentSettings.putAll(replicationEnvironmentParameters); + } + Map<String, String> environmentSettings = new HashMap<String, String>(EnvironmentFacade.ENVCONFIG_DEFAULTS); + if (environmentParameters != null && !environmentParameters.isEmpty()) + { + environmentSettings.putAll(environmentParameters); + } + + ReplicationConfig replicationConfig = new ReplicationConfig(groupName, _configuration.getName(), hostPort); + replicationConfig.setHelperHosts(helperHostPort); + replicationConfig.setDesignatedPrimary(designatedPrimary); + replicationConfig.setNodePriority(priority); + replicationConfig.setElectableGroupSizeOverride(quorumOverride); + + for (Map.Entry<String, String> configItem : replicationEnvironmentSettings.entrySet()) + { + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("Setting ReplicationConfig key " + configItem.getKey() + " to '" + configItem.getValue() + "'"); + } + replicationConfig.setConfigParam(configItem.getKey(), configItem.getValue()); + } + + EnvironmentConfig envConfig = new EnvironmentConfig(); + envConfig.setAllowCreate(true); + envConfig.setTransactional(true); + envConfig.setExceptionListener(new LoggingAsyncExceptionListener()); + envConfig.setDurability(_durability); + + for (Map.Entry<String, String> configItem : environmentSettings.entrySet()) + { + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("Setting EnvironmentConfig key " + configItem.getKey() + " to '" + configItem.getValue() + "'"); + } + envConfig.setConfigParam(configItem.getKey(), configItem.getValue()); + } + + if (createEnvironmentInSeparateThread) + { + return createEnvironmentInSeparateThread(_environmentDirectory, envConfig, replicationConfig); + } + else + { + return createEnvironment(_environmentDirectory, envConfig, replicationConfig); + } + } + + private ReplicatedEnvironment createEnvironmentInSeparateThread(final File environmentPathFile, final EnvironmentConfig envConfig, + final ReplicationConfig replicationConfig) + { + Future<ReplicatedEnvironment> environmentFuture = _environmentJobExecutor.submit(new Callable<ReplicatedEnvironment>(){ + @Override + public ReplicatedEnvironment call() throws Exception + { + String originalThreadName = Thread.currentThread().getName(); + try + { + return createEnvironment(environmentPathFile, envConfig, replicationConfig); + } + finally + { + Thread.currentThread().setName(originalThreadName); + } + }}); + + long setUpTimeOutMillis = PropUtil.parseDuration(replicationConfig.getConfigParam(ReplicationConfig.ENV_SETUP_TIMEOUT)); + try + { + return environmentFuture.get(setUpTimeOutMillis, TimeUnit.MILLISECONDS); + } + catch (InterruptedException e) + { + Thread.currentThread().interrupt(); + throw new RuntimeException("Environment creation was interrupted", e); + } + catch (ExecutionException e) + { + throw new RuntimeException("Unexpected exception on environment creation", e.getCause()); + } + catch (TimeoutException e) + { + throw new RuntimeException("JE environment has not been created in due time"); + } + } + + private ReplicatedEnvironment createEnvironment(File environmentPathFile, EnvironmentConfig envConfig, + final ReplicationConfig replicationConfig) + { + ReplicatedEnvironment environment = null; + try + { + environment = new ReplicatedEnvironment(environmentPathFile, replicationConfig, envConfig); + } + catch (final InsufficientLogException ile) + { + LOGGER.info("InsufficientLogException thrown and so full network restore required", ile); + NetworkRestore restore = new NetworkRestore(); + NetworkRestoreConfig config = new NetworkRestoreConfig(); + config.setRetainLogFiles(false); + restore.execute(ile, config); + environment = new ReplicatedEnvironment(environmentPathFile, replicationConfig, envConfig); + } + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("Environment is created for node " + _prettyGroupNodeName); + } + return environment; + } + + @Override + public Committer createCommitter(String name) + { + if (_coalescingSync) + { + return new CoalescingCommiter(name, this); + } + else + { + return Committer.IMMEDIATE_FUTURE_COMMITTER; + } + } + + public NodeState getRemoteNodeState(ReplicationNode repNode) throws IOException, ServiceConnectFailedException + { + if (repNode == null) + { + throw new IllegalArgumentException("Node cannot be null"); + } + return new DbPing(repNode, (String)_configuration.getGroupName(), DB_PING_SOCKET_TIMEOUT).getNodeState(); + } + + // For testing only + int getNumberOfElectableGroupMembers() + { + if (_state.get() != State.OPEN) + { + throw new IllegalStateException("Environment facade is not opened"); + } + return _environment.getGroup().getElectableNodes().size(); + } + + private class RemoteNodeStateLearner implements Callable<Void> + { + private Map<String, ReplicatedEnvironment.State> _previousGroupState = Collections.emptyMap(); + @Override + public Void call() + { + final Map<String, ReplicatedEnvironment.State> currentGroupState = new HashMap<String, ReplicatedEnvironment.State>(); + try + { + Set<Future<Void>> futures = new HashSet<Future<Void>>(); + + for (final ReplicationNode node : _environment.getGroup().getElectableNodes()) + { + Future<Void> future = _groupChangeExecutor.submit(new Callable<Void>() + { + @Override + public Void call() + { + DbPing ping = new DbPing(node, _configuration.getGroupName(), REMOTE_NODE_MONITOR_INTERVAL); + ReplicatedEnvironment.State nodeState; + try + { + nodeState = ping.getNodeState().getNodeState(); + } + catch (IOException e) + { + nodeState = ReplicatedEnvironment.State.UNKNOWN; + } + catch (ServiceConnectFailedException e) + { + nodeState = ReplicatedEnvironment.State.UNKNOWN; + } + + currentGroupState.put(node.getName(), nodeState); + return null; + } + }); + futures.add(future); + } + + for (Future<Void> future : futures) + { + try + { + future.get(REMOTE_NODE_MONITOR_INTERVAL, TimeUnit.MILLISECONDS); + } + catch (InterruptedException e) + { + Thread.currentThread().interrupt(); + } + catch (ExecutionException e) + { + LOGGER.warn("Cannot update node state for group " + _configuration.getGroupName(), e.getCause()); + } + catch (TimeoutException e) + { + LOGGER.warn("Timeout whilst updating node state for group " + _configuration.getGroupName()); + future.cancel(true); + } + } + + if (ReplicatedEnvironment.State.MASTER == _environment.getState()) + { + boolean stateChanged = !_previousGroupState.equals(currentGroupState); + _previousGroupState = currentGroupState; + if (stateChanged && State.OPEN == _state.get()) + { + new DatabasePinger().pingDb(ReplicatedEnvironmentFacade.this); + } + } + } + finally + { + _groupChangeExecutor.schedule(this, REMOTE_NODE_MONITOR_INTERVAL, TimeUnit.MILLISECONDS); + } + return null; + } + } + public static enum State + { + OPENING, + OPEN, + RESTARTING, + CLOSING, + CLOSED + } + + private static class DatabaseHolder + { + private final DatabaseConfig _config; + private Database _database; + + public DatabaseHolder(DatabaseConfig config) + { + _config = config; + } + + public Database getDatabase() + { + return _database; + } + + public void setDatabase(Database database) + { + _database = database; + } + + public DatabaseConfig getConfig() + { + return _config; + } + + @Override + public String toString() + { + return "DatabaseHolder [_config=" + _config + ", _database=" + _database + "]"; + } + + } + +} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacadeFactory.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacadeFactory.java new file mode 100644 index 0000000000..4df62b1d0f --- /dev/null +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacadeFactory.java @@ -0,0 +1,161 @@ +/* + * + * 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.replication; + +import java.util.Map; + +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.berkeleydb.EnvironmentFacade; +import org.apache.qpid.server.store.berkeleydb.EnvironmentFacadeFactory; + +import com.sleepycat.je.Durability; +import com.sleepycat.je.Durability.ReplicaAckPolicy; +import com.sleepycat.je.Durability.SyncPolicy; + +public class ReplicatedEnvironmentFacadeFactory implements EnvironmentFacadeFactory +{ + public static final String DURABILITY = "haDurability"; + public static final String GROUP_NAME = "haGroupName"; + public static final String HELPER_ADDRESS = "haHelperAddress"; + public static final String NODE_ADDRESS = "haNodeAddress"; + public static final String NODE_NAME = "haNodeName"; + public static final String REPLICATION_CONFIG = "haReplicationConfig"; + public static final String COALESCING_SYNC = "haCoalescingSync"; + public static final String DESIGNATED_PRIMARY = "haDesignatedPrimary"; + + private static final int DEFAULT_NODE_PRIORITY = 1; + private static final Durability DEFAULT_DURABILITY = new Durability(SyncPolicy.NO_SYNC, SyncPolicy.NO_SYNC, + ReplicaAckPolicy.SIMPLE_MAJORITY); + private static final boolean DEFAULT_COALESCING_SYNC = true; + + @Override + public EnvironmentFacade createEnvironmentFacade(VirtualHost<?> virtualHost, boolean isMessageStore) + { + final Map<String, Object> messageStoreSettings = virtualHost.getMessageStoreSettings(); + ReplicatedEnvironmentConfiguration configuration = new ReplicatedEnvironmentConfiguration() + { + @Override + public boolean isDesignatedPrimary() + { + return convertBoolean(messageStoreSettings.get(DESIGNATED_PRIMARY), false); + } + + @Override + public boolean isCoalescingSync() + { + return convertBoolean(messageStoreSettings.get(COALESCING_SYNC), DEFAULT_COALESCING_SYNC); + } + + @Override + public String getStorePath() + { + return (String) messageStoreSettings.get(MessageStore.STORE_PATH); + } + + @SuppressWarnings("unchecked") + @Override + public Map<String, String> getParameters() + { + return (Map<String, String>) messageStoreSettings.get(EnvironmentFacadeFactory.ENVIRONMENT_CONFIGURATION); + } + + @SuppressWarnings("unchecked") + @Override + public Map<String, String> getReplicationParameters() + { + return (Map<String, String>) messageStoreSettings.get(REPLICATION_CONFIG); + } + + @Override + public int getQuorumOverride() + { + return 0; + } + + @Override + public int getPriority() + { + return DEFAULT_NODE_PRIORITY; + } + + @Override + public String getName() + { + return (String)messageStoreSettings.get(NODE_NAME); + } + + @Override + public String getHostPort() + { + return (String)messageStoreSettings.get(NODE_ADDRESS); + } + + @Override + public String getHelperHostPort() + { + return (String)messageStoreSettings.get(HELPER_ADDRESS); + } + + @Override + public String getGroupName() + { + return (String)messageStoreSettings.get(GROUP_NAME); + } + + @Override + public String getDurability() + { + String durability = (String)messageStoreSettings.get(DURABILITY); + return durability == null ? DEFAULT_DURABILITY.toString() : durability; + } + }; + return new ReplicatedEnvironmentFacade(configuration); + + } + + @Override + public String getType() + { + return ReplicatedEnvironmentFacade.TYPE; + } + + private boolean convertBoolean(final Object value, boolean defaultValue) + { + if(value instanceof Boolean) + { + return (Boolean) value; + } + else if(value instanceof String) + { + return Boolean.valueOf((String) value); + } + else if(value == null) + { + return defaultValue; + } + else + { + throw new IllegalArgumentException("Cannot convert type " + value.getClass() + " to a Boolean"); + } + } + +} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/Upgrader.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/Upgrader.java index 4d536a2f95..7852e2d703 100644 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/Upgrader.java +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/Upgrader.java @@ -21,11 +21,13 @@ package org.apache.qpid.server.store.berkeleydb.upgrade; import com.sleepycat.je.Cursor; + import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import org.apache.log4j.Logger; import org.apache.qpid.server.store.StoreException; -import org.apache.qpid.server.store.berkeleydb.AbstractBDBMessageStore; +import org.apache.qpid.server.store.berkeleydb.BDBMessageStore; import com.sleepycat.bind.tuple.IntegerBinding; import com.sleepycat.bind.tuple.LongBinding; @@ -38,6 +40,8 @@ import com.sleepycat.je.OperationStatus; public class Upgrader { + private static final Logger LOGGER = Logger.getLogger(Upgrader.class); + static final String VERSION_DB_NAME = "DB_VERSION"; private Environment _environment; @@ -63,7 +67,8 @@ public class Upgrader if(versionDb.count() == 0L) { - int sourceVersion = isEmpty ? AbstractBDBMessageStore.VERSION: identifyOldStoreVersion(); + + int sourceVersion = isEmpty ? BDBMessageStore.VERSION: identifyOldStoreVersion(); DatabaseEntry key = new DatabaseEntry(); IntegerBinding.intToEntry(sourceVersion, key); DatabaseEntry value = new DatabaseEntry(); @@ -73,11 +78,17 @@ public class Upgrader } int version = getSourceVersion(versionDb); - if(version > AbstractBDBMessageStore.VERSION) + + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Source message store version is " + version); + } + + if(version > BDBMessageStore.VERSION) { throw new StoreException("Database version " + version + " is higher than the most recent known version: " - + AbstractBDBMessageStore.VERSION); + + BDBMessageStore.VERSION); } performUpgradeFromVersion(version, versionDb); } @@ -124,8 +135,9 @@ public class Upgrader } void performUpgradeFromVersion(int sourceVersion, Database versionDb) + throws StoreException { - while(sourceVersion != AbstractBDBMessageStore.VERSION) + while(sourceVersion != BDBMessageStore.VERSION) { upgrade(sourceVersion, ++sourceVersion); DatabaseEntry key = new DatabaseEntry(); @@ -136,7 +148,7 @@ public class Upgrader } } - void upgrade(final int fromVersion, final int toVersion) + void upgrade(final int fromVersion, final int toVersion) throws StoreException { try { @@ -177,7 +189,7 @@ public class Upgrader private int identifyOldStoreVersion() throws DatabaseException { - int version = 0; + int version = BDBMessageStore.VERSION; for (String databaseName : _environment.getDatabaseNames()) { if (databaseName.contains("_v")) diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreTest.java deleted file mode 100644 index c2b3aeab3e..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreTest.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * - * 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 java.io.File; -import java.net.InetAddress; - -import java.util.HashMap; -import java.util.Map; -import org.apache.commons.configuration.XMLConfiguration; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; -import org.apache.qpid.server.logging.EventLogger; -import org.apache.qpid.server.util.BrokerTestHelper; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.virtualhost.VirtualHostRegistry; -import org.apache.qpid.test.utils.QpidTestCase; -import org.apache.qpid.util.FileUtils; - -import com.sleepycat.je.Environment; -import com.sleepycat.je.EnvironmentConfig; -import com.sleepycat.je.rep.ReplicatedEnvironment; -import com.sleepycat.je.rep.ReplicationConfig; - -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - - -public class BDBHAMessageStoreTest extends QpidTestCase -{ - private static final String TEST_LOG_FILE_MAX = "1000000"; - private static final String TEST_ELECTION_RETRIES = "1000"; - private static final String TEST_NUMBER_OF_THREADS = "10"; - private static final String TEST_ENV_CONSISTENCY_TIMEOUT = "9999999"; - private String _groupName; - private String _workDir; - private int _masterPort; - private String _host; - private XMLConfiguration _configXml; - private VirtualHost _virtualHost; - private org.apache.qpid.server.model.VirtualHost _modelVhost; - - public void setUp() throws Exception - { - super.setUp(); - - _workDir = TMP_FOLDER + File.separator + getName(); - _host = InetAddress.getByName("localhost").getHostAddress(); - _groupName = "group" + getName(); - _masterPort = -1; - - FileUtils.delete(new File(_workDir), true); - _configXml = new XMLConfiguration(); - _modelVhost = mock(org.apache.qpid.server.model.VirtualHost.class); - - - BrokerTestHelper.setUp(); - } - - public void tearDown() throws Exception - { - try - { - if (_virtualHost != null) - { - _virtualHost.close(); - } - FileUtils.delete(new File(_workDir), true); - } - finally - { - BrokerTestHelper.tearDown(); - super.tearDown(); - } - } - - public void testSetSystemConfiguration() throws Exception - { - // create virtual host configuration, registry and host instance - addVirtualHostConfiguration(); - String vhostName = "test" + _masterPort; - VirtualHostConfiguration configuration = new VirtualHostConfiguration(vhostName, _configXml.subset("virtualhosts.virtualhost." + vhostName), BrokerTestHelper.createBrokerMock()); - - _virtualHost = BrokerTestHelper.createVirtualHost(configuration,new VirtualHostRegistry(new EventLogger()),_modelVhost); - BDBHAMessageStore store = (BDBHAMessageStore) _virtualHost.getMessageStore(); - - // test whether JVM system settings were applied - Environment env = store.getEnvironment(); - assertEquals("Unexpected number of cleaner threads", TEST_NUMBER_OF_THREADS, env.getConfig().getConfigParam(EnvironmentConfig.CLEANER_THREADS)); - assertEquals("Unexpected log file max", TEST_LOG_FILE_MAX, env.getConfig().getConfigParam(EnvironmentConfig.LOG_FILE_MAX)); - - ReplicatedEnvironment repEnv = store.getReplicatedEnvironment(); - assertEquals("Unexpected number of elections primary retries", TEST_ELECTION_RETRIES, - repEnv.getConfig().getConfigParam(ReplicationConfig.ELECTIONS_PRIMARY_RETRIES)); - assertEquals("Unexpected number of elections primary retries", TEST_ENV_CONSISTENCY_TIMEOUT, - repEnv.getConfig().getConfigParam(ReplicationConfig.ENV_CONSISTENCY_TIMEOUT)); - } - - private void addVirtualHostConfiguration() throws Exception - { - int port = findFreePort(); - if (_masterPort == -1) - { - _masterPort = port; - } - String nodeName = getNodeNameForNodeAt(port); - - String vhostName = "test" + port; - String vhostPrefix = "virtualhosts.virtualhost." + vhostName; - - _configXml.addProperty("virtualhosts.virtualhost.name", vhostName); - _configXml.addProperty(vhostPrefix + ".type", BDBHAVirtualHostFactory.TYPE); - - when(_modelVhost.getAttribute(eq(_modelVhost.STORE_PATH))).thenReturn(_workDir + File.separator - + port); - when(_modelVhost.getAttribute(eq("haGroupName"))).thenReturn(_groupName); - when(_modelVhost.getAttribute(eq("haNodeName"))).thenReturn(nodeName); - when(_modelVhost.getAttribute(eq("haNodeAddress"))).thenReturn(getNodeHostPortForNodeAt(port)); - when(_modelVhost.getAttribute(eq("haHelperAddress"))).thenReturn(getHelperHostPort()); - - Map<String,String> bdbEnvConfig = new HashMap<String,String>(); - bdbEnvConfig.put(EnvironmentConfig.CLEANER_THREADS, TEST_NUMBER_OF_THREADS); - bdbEnvConfig.put(EnvironmentConfig.LOG_FILE_MAX, TEST_LOG_FILE_MAX); - - when(_modelVhost.getAttribute(eq("bdbEnvironmentConfig"))).thenReturn(bdbEnvConfig); - - Map<String,String> repConfig = new HashMap<String,String>(); - repConfig.put(ReplicationConfig.ELECTIONS_PRIMARY_RETRIES, TEST_ELECTION_RETRIES); - repConfig.put(ReplicationConfig.ENV_CONSISTENCY_TIMEOUT, TEST_ENV_CONSISTENCY_TIMEOUT); - when(_modelVhost.getAttribute(eq("haReplicationConfig"))).thenReturn(repConfig); - - } - - private String getNodeNameForNodeAt(final int bdbPort) - { - return "node" + getName() + bdbPort; - } - - private String getNodeHostPortForNodeAt(final int bdbPort) - { - return _host + ":" + bdbPort; - } - - private String getHelperHostPort() - { - if (_masterPort == -1) - { - throw new IllegalStateException("Helper port not yet assigned."); - } - return _host + ":" + _masterPort; - } -} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreQuotaEventsTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreQuotaEventsTest.java index 4684358190..65830fd1c2 100644 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreQuotaEventsTest.java +++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreQuotaEventsTest.java @@ -20,17 +20,18 @@ */ package org.apache.qpid.server.store.berkeleydb; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import java.util.Collections; +import java.util.HashMap; import java.util.Map; + import org.apache.log4j.Logger; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.MessageStoreConstants; import org.apache.qpid.server.store.MessageStoreQuotaEventsTestBase; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.when; - public class BDBMessageStoreQuotaEventsTest extends MessageStoreQuotaEventsTestBase { private static final Logger _logger = Logger.getLogger(BDBMessageStoreQuotaEventsTest.class); @@ -59,16 +60,22 @@ public class BDBMessageStoreQuotaEventsTest extends MessageStoreQuotaEventsTestB return NUMBER_OF_MESSAGES_TO_OVERFILL_STORE; } + @Override - protected void applyStoreSpecificConfiguration(VirtualHost virtualHost) + protected VirtualHost<?> createVirtualHost(String storeLocation) { - _logger.debug("Applying store specific config. overfull-sze=" + OVERFULL_SIZE + ", underfull-size=" + UNDERFULL_SIZE); + _logger.debug("Applying store specific config. overfull-size=" + OVERFULL_SIZE + ", underfull-size=" + UNDERFULL_SIZE); + VirtualHost<?> vhost = mock(VirtualHost.class); + Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); + messageStoreSettings.put(MessageStore.STORE_PATH, storeLocation); + messageStoreSettings.put(MessageStore.OVERFULL_SIZE, OVERFULL_SIZE); + messageStoreSettings.put(MessageStore.UNDERFULL_SIZE, UNDERFULL_SIZE); Map<String,String> envMap = Collections.singletonMap("je.log.fileMax", MAX_BDB_LOG_SIZE); - when(virtualHost.getAttribute(eq("bdbEnvironmentConfig"))).thenReturn(envMap); - when(virtualHost.getAttribute(eq(MessageStoreConstants.OVERFULL_SIZE_ATTRIBUTE))).thenReturn(OVERFULL_SIZE); - when(virtualHost.getAttribute(eq(MessageStoreConstants.UNDERFULL_SIZE_ATTRIBUTE))).thenReturn(UNDERFULL_SIZE); - + messageStoreSettings.put(EnvironmentFacadeFactory.ENVIRONMENT_CONFIGURATION, envMap); + when(vhost.getMessageStoreSettings()).thenReturn(messageStoreSettings); + when(vhost.getName()).thenReturn("test"); + return vhost; } @Override diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAMessageStoreSmokeTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAMessageStoreSmokeTest.java deleted file mode 100644 index 7f7b65f315..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAMessageStoreSmokeTest.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.commons.configuration.ConfigurationException; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.util.ServerScopedRuntimeException; -import org.apache.qpid.test.utils.QpidTestCase; - -import static org.mockito.Mockito.mock; - -public class HAMessageStoreSmokeTest extends QpidTestCase -{ - private final BDBHAMessageStore _store = new BDBHAMessageStore(); - - public void testMissingHAConfigThrowsException() throws Exception - { - try - { - _store.configure(mock(VirtualHost.class)); - fail("Expected an exception to be thrown"); - } - catch (ServerScopedRuntimeException ce) - { - assertTrue(ce.getMessage().contains("BDB HA configuration key not found")); - } - } -} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacadeTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacadeTest.java new file mode 100644 index 0000000000..b19e18b204 --- /dev/null +++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacadeTest.java @@ -0,0 +1,128 @@ +/* + * + * 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 java.io.File; +import java.util.Collections; + +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.util.FileUtils; + +import com.sleepycat.je.Database; +import com.sleepycat.je.DatabaseConfig; +import com.sleepycat.je.Environment; + +public class StandardEnvironmentFacadeTest extends QpidTestCase +{ + protected File _storePath; + protected EnvironmentFacade _environmentFacade; + + protected void setUp() throws Exception + { + super.setUp(); + _storePath = new File(TMP_FOLDER + File.separator + "bdb" + File.separator + getTestName()); + } + + protected void tearDown() throws Exception + { + try + { + super.tearDown(); + if (_environmentFacade != null) + { + _environmentFacade.close(); + } + } + finally + { + if (_storePath != null) + { + FileUtils.delete(_storePath, true); + } + } + } + + public void testEnvironmentFacade() throws Exception + { + EnvironmentFacade ef = getEnvironmentFacade(); + assertNotNull("Environment should not be null", ef); + Environment e = ef.getEnvironment(); + assertTrue("Environment is not valid", e.isValid()); + } + + public void testClose() throws Exception + { + EnvironmentFacade ef = getEnvironmentFacade(); + ef.close(); + Environment e = ef.getEnvironment(); + + assertNull("Environment should be null after facade close", e); + } + + public void testOpenDatabases() throws Exception + { + EnvironmentFacade ef = getEnvironmentFacade(); + DatabaseConfig dbConfig = new DatabaseConfig(); + dbConfig.setTransactional(true); + dbConfig.setAllowCreate(true); + ef.openDatabases(dbConfig, "test1", "test2"); + Database test1 = ef.getOpenDatabase("test1"); + Database test2 = ef.getOpenDatabase("test2"); + + assertEquals("Unexpected name for open database test1", "test1" , test1.getDatabaseName()); + assertEquals("Unexpected name for open database test2", "test2" , test2.getDatabaseName()); + } + + public void testGetOpenDatabaseForNonExistingDatabase() throws Exception + { + EnvironmentFacade ef = getEnvironmentFacade(); + DatabaseConfig dbConfig = new DatabaseConfig(); + dbConfig.setTransactional(true); + dbConfig.setAllowCreate(true); + ef.openDatabases(dbConfig, "test1"); + Database test1 = ef.getOpenDatabase("test1"); + assertEquals("Unexpected name for open database test1", "test1" , test1.getDatabaseName()); + try + { + ef.getOpenDatabase("test2"); + fail("An exception should be thrown for the non existing database"); + } + catch(IllegalArgumentException e) + { + assertEquals("Unexpected exception message", "Database with name 'test2' has not been opened", e.getMessage()); + } + } + + EnvironmentFacade getEnvironmentFacade() throws Exception + { + if (_environmentFacade == null) + { + _environmentFacade = createEnvironmentFacade(); + } + return _environmentFacade; + } + + EnvironmentFacade createEnvironmentFacade() + { + return new StandardEnvironmentFacade(_storePath.getAbsolutePath(), Collections.<String, String>emptyMap()); + } + +} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/VirtualHostTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/VirtualHostTest.java new file mode 100644 index 0000000000..2caf85966c --- /dev/null +++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/VirtualHostTest.java @@ -0,0 +1,156 @@ +/* + * + * 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 static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfigurationEntryStore; +import org.apache.qpid.server.configuration.RecovererProvider; +import org.apache.qpid.server.configuration.startup.VirtualHostRecoverer; +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.stats.StatisticsGatherer; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacade; +import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacadeFactory; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.util.FileUtils; + +import com.sleepycat.je.rep.ReplicatedEnvironment; +import com.sleepycat.je.rep.ReplicationConfig; + +public class VirtualHostTest extends QpidTestCase +{ + + private Broker<?> _broker; + private StatisticsGatherer _statisticsGatherer; + private RecovererProvider _recovererProvider; + private File _bdbStorePath; + private VirtualHost<?> _host; + private ConfigurationEntryStore _store; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + _store = mock(ConfigurationEntryStore.class); + _broker = BrokerTestHelper.createBrokerMock(); + TaskExecutor taslExecutor = mock(TaskExecutor.class); + when(taslExecutor.isTaskExecutorThread()).thenReturn(true); + when(_broker.getTaskExecutor()).thenReturn(taslExecutor); + + _statisticsGatherer = mock(StatisticsGatherer.class); + + _bdbStorePath = new File(TMP_FOLDER, getTestName() + "." + System.currentTimeMillis()); + _bdbStorePath.deleteOnExit(); + } + + @Override + protected void tearDown() throws Exception + { + try + { + if (_host != null) + { + _host.setDesiredState(_host.getState(), State.STOPPED); + } + } + finally + { + if (_bdbStorePath != null) + { + FileUtils.delete(_bdbStorePath, true); + } + super.tearDown(); + } + } + + public void testCreateBdbHaVirtualHostFromConfigurationEntry() + { + String repStreamTimeout = "2 h"; + String nodeName = "node"; + String groupName = "group"; + String nodeHostPort = "localhost:" + findFreePort(); + String helperHostPort = nodeHostPort; + String durability = "NO_SYNC,SYNC,NONE"; + String virtualHostName = getName(); + + Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); + messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.NODE_NAME, nodeName); + messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.GROUP_NAME, groupName); + messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.NODE_ADDRESS, nodeHostPort); + messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.HELPER_ADDRESS, helperHostPort); + messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.DURABILITY, durability); + + messageStoreSettings.put(MessageStore.STORE_PATH, _bdbStorePath.getAbsolutePath()); + messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.REPLICATION_CONFIG, + Collections.singletonMap(ReplicationConfig.REP_STREAM_TIMEOUT, repStreamTimeout)); + + Map<String, Object> virtualHostAttributes = new HashMap<String, Object>(); + virtualHostAttributes.put(VirtualHost.NAME, virtualHostName); + virtualHostAttributes.put(VirtualHost.TYPE, BDBHAVirtualHostFactory.TYPE); + virtualHostAttributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, messageStoreSettings); + + _host = createHost(virtualHostAttributes); + _host.setDesiredState(State.INITIALISING, State.ACTIVE); + + assertEquals("Unexpected virtual host name", virtualHostName, _host.getName()); + assertEquals("Unexpected host type", BDBHAVirtualHostFactory.TYPE, _host.getType()); + + assertEquals(messageStoreSettings, _host.getMessageStoreSettings()); + + BDBMessageStore messageStore = (BDBMessageStore) _host.getMessageStore(); + ReplicatedEnvironment environment = (ReplicatedEnvironment) messageStore.getEnvironmentFacade().getEnvironment(); + ReplicationConfig replicationConfig = environment.getRepConfig(); + + assertEquals(nodeName, environment.getNodeName()); + assertEquals(groupName, environment.getGroup().getName()); + assertEquals(nodeHostPort, replicationConfig.getNodeHostPort()); + assertEquals(helperHostPort, replicationConfig.getHelperHosts()); + assertEquals(durability, environment.getConfig().getDurability().toString()); + assertEquals("Unexpected JE replication stream timeout", repStreamTimeout, replicationConfig.getConfigParam(ReplicationConfig.REP_STREAM_TIMEOUT)); + + } + + + private VirtualHost<?> createHost(Map<String, Object> attributes) + { + ConfigurationEntry entry = new ConfigurationEntry(UUID.randomUUID(), VirtualHost.class.getSimpleName(), attributes, + Collections.<UUID>emptySet(), _store); + + return new VirtualHostRecoverer(_statisticsGatherer).create(_recovererProvider, entry, _broker); + } + +} + +
\ No newline at end of file diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacadeTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacadeTest.java new file mode 100644 index 0000000000..cd7dd69c46 --- /dev/null +++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacadeTest.java @@ -0,0 +1,336 @@ +/* + * + * 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.replication; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.store.berkeleydb.EnvironmentFacade; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.test.utils.TestFileUtils; +import org.apache.qpid.util.FileUtils; + +import com.sleepycat.je.Database; +import com.sleepycat.je.DatabaseConfig; +import com.sleepycat.je.Durability; +import com.sleepycat.je.Environment; +import com.sleepycat.je.rep.ReplicatedEnvironment.State; +import com.sleepycat.je.rep.ReplicationConfig; +import com.sleepycat.je.rep.StateChangeEvent; +import com.sleepycat.je.rep.StateChangeListener; + +public class ReplicatedEnvironmentFacadeTest extends QpidTestCase +{ + + private static final int TEST_NODE_PORT = new QpidTestCase().findFreePort(); + private static final int LISTENER_TIMEOUT = 5; + private static final int WAIT_STATE_CHANGE_TIMEOUT = 30; + private static final String TEST_GROUP_NAME = "testGroupName"; + private static final String TEST_NODE_NAME = "testNodeName"; + private static final String TEST_NODE_HOST_PORT = "localhost:" + TEST_NODE_PORT; + private static final String TEST_NODE_HELPER_HOST_PORT = TEST_NODE_HOST_PORT; + private static final String TEST_DURABILITY = Durability.parse("NO_SYNC,NO_SYNC,SIMPLE_MAJORITY").toString(); + private static final boolean TEST_DESIGNATED_PRIMARY = false; + private static final boolean TEST_COALESCING_SYNC = true; + private static final int TEST_PRIORITY = 1; + private static final int TEST_ELECTABLE_GROUP_OVERRIDE = 0; + + private File _storePath; + private final Map<String, ReplicatedEnvironmentFacade> _nodes = new HashMap<String, ReplicatedEnvironmentFacade>(); + private VirtualHost _virtualHost = mock(VirtualHost.class); + + public void setUp() throws Exception + { + super.setUp(); + + TaskExecutor taskExecutor = mock(TaskExecutor.class); + when(taskExecutor.isTaskExecutorThread()).thenReturn(true); + when(_virtualHost.getTaskExecutor()).thenReturn(taskExecutor); + + _storePath = TestFileUtils.createTestDirectory("bdb", true); + + setTestSystemProperty(ReplicatedEnvironmentFacade.DB_PING_SOCKET_TIMEOUT_PROPERTY_NAME, "100"); + } + + @Override + public void tearDown() throws Exception + { + try + { + for (EnvironmentFacade ef : _nodes.values()) + { + ef.close(); + } + } + finally + { + try + { + if (_storePath != null) + { + FileUtils.delete(_storePath, true); + } + } + finally + { + super.tearDown(); + } + } + } + public void testEnvironmentFacade() throws Exception + { + EnvironmentFacade ef = createMaster(); + assertNotNull("Environment should not be null", ef); + Environment e = ef.getEnvironment(); + assertTrue("Environment is not valid", e.isValid()); + } + + public void testClose() throws Exception + { + EnvironmentFacade ef = createMaster(); + ef.close(); + Environment e = ef.getEnvironment(); + + assertNull("Environment should be null after facade close", e); + } + + public void testOpenDatabases() throws Exception + { + EnvironmentFacade ef = createMaster(); + DatabaseConfig dbConfig = new DatabaseConfig(); + dbConfig.setTransactional(true); + dbConfig.setAllowCreate(true); + ef.openDatabases(dbConfig, "test1", "test2"); + Database test1 = ef.getOpenDatabase("test1"); + Database test2 = ef.getOpenDatabase("test2"); + + assertEquals("Unexpected name for open database test1", "test1" , test1.getDatabaseName()); + assertEquals("Unexpected name for open database test2", "test2" , test2.getDatabaseName()); + } + + public void testGetOpenDatabaseForNonExistingDatabase() throws Exception + { + EnvironmentFacade ef = createMaster(); + DatabaseConfig dbConfig = new DatabaseConfig(); + dbConfig.setTransactional(true); + dbConfig.setAllowCreate(true); + ef.openDatabases(dbConfig, "test1"); + Database test1 = ef.getOpenDatabase("test1"); + assertEquals("Unexpected name for open database test1", "test1" , test1.getDatabaseName()); + try + { + ef.getOpenDatabase("test2"); + fail("An exception should be thrown for the non existing database"); + } + catch(IllegalArgumentException e) + { + assertEquals("Unexpected exception message", "Database with name 'test2' has never been requested to be opened", e.getMessage()); + } + } + + public void testGetGroupName() throws Exception + { + assertEquals("Unexpected group name", TEST_GROUP_NAME, createMaster().getGroupName()); + } + + public void testGetNodeName() throws Exception + { + assertEquals("Unexpected group name", TEST_NODE_NAME, createMaster().getNodeName()); + } + + public void testLastKnownReplicationTransactionId() throws Exception + { + ReplicatedEnvironmentFacade master = createMaster(); + long lastKnownReplicationTransactionId = master.getLastKnownReplicationTransactionId(); + assertTrue("Unexpected LastKnownReplicationTransactionId " + lastKnownReplicationTransactionId, lastKnownReplicationTransactionId > 0); + } + + public void testGetNodeHostPort() throws Exception + { + assertEquals("Unexpected node host port", TEST_NODE_HOST_PORT, createMaster().getHostPort()); + } + + public void testGetHelperHostPort() throws Exception + { + assertEquals("Unexpected node helper host port", TEST_NODE_HELPER_HOST_PORT, createMaster().getHelperHostPort()); + } + + public void testGetDurability() throws Exception + { + assertEquals("Unexpected durability", TEST_DURABILITY.toString(), createMaster().getDurability()); + } + + public void testIsCoalescingSync() throws Exception + { + assertEquals("Unexpected coalescing sync", TEST_COALESCING_SYNC, createMaster().isCoalescingSync()); + } + + public void testGetNodeState() throws Exception + { + assertEquals("Unexpected state", State.MASTER.name(), createMaster().getNodeState()); + } + + + public void testPriority() throws Exception + { + ReplicatedEnvironmentFacade facade = createMaster(); + assertEquals("Unexpected priority", TEST_PRIORITY, facade.getPriority()); + Future<Void> future = facade.setPriority(TEST_PRIORITY + 1); + future.get(5, TimeUnit.SECONDS); + assertEquals("Unexpected priority after change", TEST_PRIORITY + 1, facade.getPriority()); + } + + public void testDesignatedPrimary() throws Exception + { + ReplicatedEnvironmentFacade master = createMaster(); + assertEquals("Unexpected designated primary", TEST_DESIGNATED_PRIMARY, master.isDesignatedPrimary()); + Future<Void> future = master.setDesignatedPrimary(!TEST_DESIGNATED_PRIMARY); + future.get(5, TimeUnit.SECONDS); + assertEquals("Unexpected designated primary after change", !TEST_DESIGNATED_PRIMARY, master.isDesignatedPrimary()); + } + + public void testElectableGroupSizeOverride() throws Exception + { + ReplicatedEnvironmentFacade facade = createMaster(); + assertEquals("Unexpected Electable Group Size Override", TEST_ELECTABLE_GROUP_OVERRIDE, facade.getElectableGroupSizeOverride()); + Future<Void> future = facade.setElectableGroupSizeOverride(TEST_ELECTABLE_GROUP_OVERRIDE + 1); + future.get(5, TimeUnit.SECONDS); + assertEquals("Unexpected Electable Group Size Override after change", TEST_ELECTABLE_GROUP_OVERRIDE + 1, facade.getElectableGroupSizeOverride()); + } + + public void testEnvironmentAutomaticallyRestartsAndBecomesUnknownOnInsufficientReplicas() throws Exception + { + final CountDownLatch masterLatch = new CountDownLatch(1); + final AtomicInteger masterStateChangeCount = new AtomicInteger(); + final CountDownLatch unknownLatch = new CountDownLatch(1); + final AtomicInteger unknownStateChangeCount = new AtomicInteger(); + StateChangeListener stateChangeListener = new StateChangeListener() + { + @Override + public void stateChange(StateChangeEvent stateChangeEvent) throws RuntimeException + { + if (stateChangeEvent.getState() == State.MASTER) + { + masterStateChangeCount.incrementAndGet(); + masterLatch.countDown(); + } + else if (stateChangeEvent.getState() == State.UNKNOWN) + { + unknownStateChangeCount.incrementAndGet(); + unknownLatch.countDown(); + } + } + }; + + addNode(State.MASTER, stateChangeListener); + assertTrue("Master was not started", masterLatch.await(LISTENER_TIMEOUT, TimeUnit.SECONDS)); + + int replica1Port = getNextAvailable(TEST_NODE_PORT + 1); + String node1NodeHostPort = "localhost:" + replica1Port; + int replica2Port = getNextAvailable(replica1Port + 1); + String node2NodeHostPort = "localhost:" + replica2Port; + + ReplicatedEnvironmentFacade replica1 = createReplica(TEST_NODE_NAME + "_1", node1NodeHostPort); + ReplicatedEnvironmentFacade replica2 = createReplica(TEST_NODE_NAME + "_2", node2NodeHostPort); + + // close replicas + replica1.close(); + replica2.close(); + + assertTrue("Environment should be recreated and go into unknown state", + unknownLatch.await(WAIT_STATE_CHANGE_TIMEOUT, TimeUnit.SECONDS)); + + assertEquals("Node made master an unexpected number of times", 1, masterStateChangeCount.get()); + assertEquals("Node made unknown an unexpected number of times", 1, unknownStateChangeCount.get()); + } + + public void testCloseStateTransitions() throws Exception + { + ReplicatedEnvironmentFacade replicatedEnvironmentFacade = createMaster(); + + assertEquals("Unexpected state " + replicatedEnvironmentFacade.getFacadeState(), ReplicatedEnvironmentFacade.State.OPEN, replicatedEnvironmentFacade.getFacadeState()); + replicatedEnvironmentFacade.close(); + assertEquals("Unexpected state " + replicatedEnvironmentFacade.getFacadeState(), ReplicatedEnvironmentFacade.State.CLOSED, replicatedEnvironmentFacade.getFacadeState()); + } + + private ReplicatedEnvironmentFacade createMaster() throws Exception + { + TestStateChangeListener stateChangeListener = new TestStateChangeListener(State.MASTER); + ReplicatedEnvironmentFacade env = addNode(State.MASTER, stateChangeListener); + assertTrue("Environment was not created", stateChangeListener.awaitForStateChange(LISTENER_TIMEOUT, TimeUnit.SECONDS)); + return env; + } + + private ReplicatedEnvironmentFacade createReplica(String nodeName, String nodeHostPort) throws Exception + { + TestStateChangeListener testStateChangeListener = new TestStateChangeListener(State.REPLICA); + ReplicatedEnvironmentFacade replicaEnvironmentFacade = addNode(nodeName, nodeHostPort, TEST_DESIGNATED_PRIMARY, State.REPLICA, testStateChangeListener); + boolean awaitForStateChange = testStateChangeListener.awaitForStateChange(LISTENER_TIMEOUT, TimeUnit.SECONDS); + assertTrue("Replica " + nodeName + " did not go into desired state; current actual state is " + testStateChangeListener.getCurrentActualState(), awaitForStateChange); + return replicaEnvironmentFacade; + } + + private ReplicatedEnvironmentFacade addNode(String nodeName, String nodeHostPort, boolean designatedPrimary, + State desiredState, StateChangeListener stateChangeListener) + { + ReplicatedEnvironmentConfiguration config = createReplicatedEnvironmentConfiguration(nodeName, nodeHostPort, designatedPrimary); + ReplicatedEnvironmentFacade ref = new ReplicatedEnvironmentFacade(config); + ref.setStateChangeListener(stateChangeListener); + _nodes.put(nodeName, ref); + return ref; + } + + private ReplicatedEnvironmentFacade addNode(State desiredState, StateChangeListener stateChangeListener) + { + return addNode(TEST_NODE_NAME, TEST_NODE_HOST_PORT, TEST_DESIGNATED_PRIMARY, desiredState, stateChangeListener); + } + + private ReplicatedEnvironmentConfiguration createReplicatedEnvironmentConfiguration(String nodeName, String nodeHostPort, boolean designatedPrimary) + { + ReplicatedEnvironmentConfiguration node = mock(ReplicatedEnvironmentConfiguration.class); + when(node.getName()).thenReturn(nodeName); + when(node.getHostPort()).thenReturn(nodeHostPort); + when(node.isDesignatedPrimary()).thenReturn(designatedPrimary); + when(node.getQuorumOverride()).thenReturn(TEST_ELECTABLE_GROUP_OVERRIDE); + when(node.getPriority()).thenReturn(TEST_PRIORITY); + when(node.getGroupName()).thenReturn(TEST_GROUP_NAME); + when(node.getHelperHostPort()).thenReturn(TEST_NODE_HELPER_HOST_PORT); + when(node.getDurability()).thenReturn(TEST_DURABILITY); + when(node.isCoalescingSync()).thenReturn(TEST_COALESCING_SYNC); + + Map<String, String> repConfig = new HashMap<String, String>(); + repConfig.put(ReplicationConfig.REPLICA_ACK_TIMEOUT, "2 s"); + repConfig.put(ReplicationConfig.INSUFFICIENT_REPLICAS_TIMEOUT, "2 s"); + when(node.getReplicationParameters()).thenReturn(repConfig); + when(node.getStorePath()).thenReturn(new File(_storePath, nodeName).getAbsolutePath()); + return node; + } +} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/TestStateChangeListener.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/TestStateChangeListener.java new file mode 100644 index 0000000000..0870191b35 --- /dev/null +++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/TestStateChangeListener.java @@ -0,0 +1,70 @@ +/* + * + * 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.replication; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import com.sleepycat.je.rep.ReplicatedEnvironment.State; +import com.sleepycat.je.rep.StateChangeEvent; +import com.sleepycat.je.rep.StateChangeListener; + +class TestStateChangeListener implements StateChangeListener +{ + private final Set<State> _expectedStates; + private final CountDownLatch _latch; + private final AtomicReference<State> _currentActualState = new AtomicReference<State>(); + + public TestStateChangeListener(State expectedState) + { + this(Collections.singleton(expectedState)); + } + + public TestStateChangeListener(Set<State> expectedStates) + { + _expectedStates = new HashSet<State>(expectedStates); + _latch = new CountDownLatch(1); + } + + @Override + public void stateChange(StateChangeEvent stateChangeEvent) throws RuntimeException + { + _currentActualState.set(stateChangeEvent.getState()); + if (_expectedStates.contains(stateChangeEvent.getState())) + { + _latch.countDown(); + } + } + + public boolean awaitForStateChange(long timeout, TimeUnit timeUnit) throws InterruptedException + { + return _latch.await(timeout, timeUnit); + } + + public State getCurrentActualState() + { + return _currentActualState.get(); + } +}
\ No newline at end of file diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderFailOnNewerVersionTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderFailOnNewerVersionTest.java index 400ac12792..810f4a1fca 100644 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderFailOnNewerVersionTest.java +++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderFailOnNewerVersionTest.java @@ -26,7 +26,7 @@ import com.sleepycat.je.Database; import com.sleepycat.je.DatabaseConfig; import com.sleepycat.je.DatabaseEntry; import com.sleepycat.je.OperationStatus; -import org.apache.qpid.server.store.berkeleydb.AbstractBDBMessageStore; +import org.apache.qpid.server.store.berkeleydb.BDBMessageStore; import org.apache.qpid.server.util.ServerScopedRuntimeException; public class UpgraderFailOnNewerVersionTest extends AbstractUpgradeTestCase @@ -94,7 +94,7 @@ public class UpgraderFailOnNewerVersionTest extends AbstractUpgradeTestCase catch(ServerScopedRuntimeException ex) { assertEquals("Incorrect exception thrown", "Database version 999 is higher than the most recent known version: " - + AbstractBDBMessageStore.VERSION, ex.getMessage()); + + BDBMessageStore.VERSION, ex.getMessage()); } } diff --git a/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBBackupTest.java b/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBBackupTest.java index 1b9fa0be9c..67c89718f6 100644 --- a/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBBackupTest.java +++ b/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBBackupTest.java @@ -31,6 +31,8 @@ import javax.jms.MessageConsumer; import javax.jms.Session; import org.apache.log4j.Logger; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.test.utils.Piper; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.util.FileUtils; @@ -59,12 +61,9 @@ public class BDBBackupTest extends QpidBrokerTestCase super.setUp(); _backupToDir = new File(SYSTEM_TMP_DIR + File.separator + getTestName()); _backupToDir.mkdirs(); - - final String qpidWork = getBroker(DEFAULT_PORT).getWorkingDirectory(); - - // It would be preferable to lookup the store path using #getConfigurationStringProperty("virtualhosts...") - // but the config as known to QBTC does not pull-in the virtualhost section from its separate source file - _backupFromDir = new File(qpidWork + File.separator + TEST_VHOST + "-store"); + Map<String, Object> virtualHostAttributes = getBrokerConfiguration().getObjectAttributes(TEST_VHOST); + Map<String, Object> messageStoreSettings = (Map<String, Object>) virtualHostAttributes.get(VirtualHost.MESSAGE_STORE_SETTINGS); + _backupFromDir = new File((String)messageStoreSettings.get(MessageStore.STORE_PATH)); boolean fromDirExistsAndIsDir = _backupFromDir.isDirectory(); assertTrue("backupFromDir " + _backupFromDir + " should already exist", fromDirExistsAndIsDir); } diff --git a/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java b/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java index bd0411619e..835deb4a4c 100644 --- a/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java +++ b/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java @@ -20,12 +20,15 @@ */ package org.apache.qpid.server.store.berkeleydb; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import java.io.File; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.List; import java.util.UUID; -import org.apache.qpid.server.store.StoreException; + import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.ContentHeaderBody; @@ -34,16 +37,19 @@ import org.apache.qpid.framing.ProtocolVersion; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.EnqueueableMessage; -import org.apache.qpid.server.protocol.v0_10.MessageMetaDataType_0_10; -import org.apache.qpid.server.protocol.v0_8.MessageMetaData; -import org.apache.qpid.server.protocol.v0_10.MessageMetaData_0_10; import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.protocol.v0_10.MessageMetaDataType_0_10; +import org.apache.qpid.server.protocol.v0_10.MessageMetaData_0_10; +import org.apache.qpid.server.protocol.v0_8.MessageMetaData; import org.apache.qpid.server.protocol.v0_8.MessageMetaDataType_0_8; -import org.apache.qpid.server.store.MessageStoreTest; import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.MessageStoreRecoveryHandler; +import org.apache.qpid.server.store.MessageStoreRecoveryHandler.StoredMessageRecoveryHandler; +import org.apache.qpid.server.store.MessageStoreTest; import org.apache.qpid.server.store.StorableMessageMetaData; +import org.apache.qpid.server.store.StoreException; import org.apache.qpid.server.store.StoredMessage; import org.apache.qpid.server.store.Transaction; import org.apache.qpid.server.store.TransactionLogResource; @@ -73,7 +79,7 @@ public class BDBMessageStoreTest extends MessageStoreTest { MessageStore store = getVirtualHost().getMessageStore(); - AbstractBDBMessageStore bdbStore = assertBDBStore(store); + BDBMessageStore bdbStore = assertBDBStore(store); // Create content ByteBuffers. // Split the content into 2 chunks for the 0-8 message, as per broker behaviour. @@ -126,7 +132,7 @@ public class BDBMessageStoreTest extends MessageStoreTest /* * reload the store only (read-only) */ - AbstractBDBMessageStore readOnlyStore = reloadStore(bdbStore); + BDBMessageStore readOnlyStore = reloadStore(bdbStore); /* * Read back and validate the 0-8 message metadata and content @@ -225,14 +231,17 @@ public class BDBMessageStoreTest extends MessageStoreTest * Use this method instead of reloading the virtual host like other tests in order * to avoid the recovery handler deleting the message for not being on a queue. */ - private AbstractBDBMessageStore reloadStore(AbstractBDBMessageStore messageStore) throws Exception + private BDBMessageStore reloadStore(BDBMessageStore messageStore) throws Exception { messageStore.close(); - AbstractBDBMessageStore newStore = new BDBMessageStore(); - newStore.configure(getVirtualHostModel(),true); + BDBMessageStore newStore = new BDBMessageStore(); + + MessageStoreRecoveryHandler recoveryHandler = mock(MessageStoreRecoveryHandler.class); + when(recoveryHandler.begin()).thenReturn(mock(StoredMessageRecoveryHandler.class)); + newStore.configureMessageStore(getVirtualHostModel(), recoveryHandler, null); - newStore.startWithNoRecover(); + newStore.activate(); return newStore; } @@ -287,7 +296,7 @@ public class BDBMessageStoreTest extends MessageStoreTest public void testGetContentWithOffset() throws Exception { MessageStore store = getVirtualHost().getMessageStore(); - AbstractBDBMessageStore bdbStore = assertBDBStore(store); + BDBMessageStore bdbStore = assertBDBStore(store); StoredMessage<MessageMetaData> storedMessage_0_8 = createAndStoreSingleChunkMessage_0_8(store); long messageid_0_8 = storedMessage_0_8.getMessageNumber(); @@ -347,7 +356,7 @@ public class BDBMessageStoreTest extends MessageStoreTest public void testMessageCreationAndRemoval() throws Exception { MessageStore store = getVirtualHost().getMessageStore(); - AbstractBDBMessageStore bdbStore = assertBDBStore(store); + BDBMessageStore bdbStore = assertBDBStore(store); StoredMessage<MessageMetaData> storedMessage_0_8 = createAndStoreSingleChunkMessage_0_8(store); long messageid_0_8 = storedMessage_0_8.getMessageNumber(); @@ -372,12 +381,12 @@ public class BDBMessageStoreTest extends MessageStoreTest assertEquals("Retrieved content when none was expected", 0, bdbStore.getContent(messageid_0_8, 0, dst)); } - private AbstractBDBMessageStore assertBDBStore(MessageStore store) + private BDBMessageStore assertBDBStore(MessageStore store) { assertEquals("Test requires an instance of BDBMessageStore to proceed", BDBMessageStore.class, store.getClass()); - return (AbstractBDBMessageStore) store; + return (BDBMessageStore) store; } private StoredMessage<MessageMetaData> createAndStoreSingleChunkMessage_0_8(MessageStore store) @@ -410,7 +419,7 @@ public class BDBMessageStoreTest extends MessageStoreTest { MessageStore log = getVirtualHost().getMessageStore(); - AbstractBDBMessageStore bdbStore = assertBDBStore(log); + BDBMessageStore bdbStore = assertBDBStore(log); final UUID mockQueueId = UUIDGenerator.generateRandomUUID(); TransactionLogResource mockQueue = new TransactionLogResource() @@ -460,7 +469,7 @@ public class BDBMessageStoreTest extends MessageStoreTest { MessageStore log = getVirtualHost().getMessageStore(); - AbstractBDBMessageStore bdbStore = assertBDBStore(log); + BDBMessageStore bdbStore = assertBDBStore(log); final UUID mockQueueId = UUIDGenerator.generateRandomUUID(); TransactionLogResource mockQueue = new TransactionLogResource() @@ -506,7 +515,7 @@ public class BDBMessageStoreTest extends MessageStoreTest public void testOnDelete() throws Exception { MessageStore log = getVirtualHost().getMessageStore(); - AbstractBDBMessageStore bdbStore = assertBDBStore(log); + BDBMessageStore bdbStore = assertBDBStore(log); String storeLocation = bdbStore.getStoreLocation(); File location = new File(storeLocation); @@ -529,7 +538,7 @@ public class BDBMessageStoreTest extends MessageStoreTest { MessageStore log = getVirtualHost().getMessageStore(); - AbstractBDBMessageStore bdbStore = assertBDBStore(log); + BDBMessageStore bdbStore = assertBDBStore(log); final UUID mockQueueId = UUIDGenerator.generateRandomUUID(); TransactionLogResource mockQueue = new TransactionLogResource() diff --git a/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBUpgradeTest.java b/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBUpgradeTest.java index 755168ca9c..cb56a60119 100644 --- a/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBUpgradeTest.java +++ b/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBUpgradeTest.java @@ -22,6 +22,7 @@ package org.apache.qpid.server.store.berkeleydb; import java.io.File; import java.io.InputStream; +import java.util.Map; import javax.jms.Connection; import javax.jms.DeliveryMode; @@ -43,8 +44,11 @@ import javax.management.openmbean.TabularDataSupport; import org.apache.qpid.management.common.mbeans.ManagedExchange; import org.apache.qpid.management.common.mbeans.ManagedQueue; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.test.utils.JMXTestUtils; import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.test.utils.TestBrokerConfiguration; import org.apache.qpid.util.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -72,7 +76,7 @@ public class BDBUpgradeTest extends QpidBrokerTestCase private static final String QUEUE_NAME="myUpgradeQueue"; private static final String NON_DURABLE_QUEUE_NAME="queue-non-durable"; private static final String PRIORITY_QUEUE_NAME="myPriorityQueue"; - private static final String QUEUE_WITH_DLQ_NAME="myQueueWithDLQ"; + private static final String QUEUE_WITH_DLQ_NAME="myQueueWithDLQ"; private String _storeLocation; @@ -80,7 +84,10 @@ public class BDBUpgradeTest extends QpidBrokerTestCase public void setUp() throws Exception { assertNotNull("QPID_WORK must be set", QPID_WORK_ORIG); - _storeLocation = getWorkDirBaseDir() + File.separator + "test-store"; + Map<String, Object> virtualHostAttributes = getBrokerConfiguration().getObjectAttributes(TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST); + @SuppressWarnings("unchecked") + Map<String, Object> messageStoreSettings = (Map<String, Object>) virtualHostAttributes.get(VirtualHost.MESSAGE_STORE_SETTINGS); + _storeLocation = (String)messageStoreSettings.get(MessageStore.STORE_PATH); //Clear the two target directories if they exist. File directory = new File(_storeLocation); @@ -98,11 +105,6 @@ public class BDBUpgradeTest extends QpidBrokerTestCase super.setUp(); } - private String getWorkDirBaseDir() - { - return QPID_WORK_ORIG + (isInternalBroker() ? "" : "/" + getPort()); - } - /** * Test that the selector applied to the DurableSubscription was successfully * transfered to the new store, and functions as expected with continued use @@ -501,7 +503,7 @@ public class BDBUpgradeTest extends QpidBrokerTestCase return send; } - + /** * Generates a string of a given length consisting of the sequence 0,1,2,..,9,0,1,2. * diff --git a/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.java b/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.java index 4b50121a7a..e8d18971ad 100644 --- a/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.java +++ b/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.java @@ -38,6 +38,7 @@ import org.apache.log4j.Logger; import org.apache.qpid.jms.ConnectionURL; import org.apache.qpid.management.common.mbeans.ManagedBroker; import org.apache.qpid.server.store.berkeleydb.jmx.ManagedBDBHAMessageStore; +import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacade; import org.apache.qpid.test.utils.JMXTestUtils; import org.apache.qpid.test.utils.QpidBrokerTestCase; @@ -143,7 +144,7 @@ public class HAClusterManagementTest extends QpidBrokerTestCase CompositeData row = groupMembers.get(new Object[] {nodeName}); assertNotNull("Table does not contain row for node name " + nodeName, row); - assertEquals(nodeHostPort, row.get(BDBHAMessageStore.GRP_MEM_COL_NODE_HOST_PORT)); + assertEquals(nodeHostPort, row.get(ReplicatedEnvironmentFacade.GRP_MEM_COL_NODE_HOST_PORT)); } } diff --git a/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.java b/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.java index 95626f7fa5..248cd7dc3d 100644 --- a/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.java +++ b/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.java @@ -34,8 +34,6 @@ import org.apache.qpid.server.store.berkeleydb.jmx.ManagedBDBHAMessageStore; import org.apache.qpid.test.utils.JMXTestUtils; import org.apache.qpid.test.utils.QpidBrokerTestCase; -import com.sleepycat.je.rep.ReplicationConfig; - public class HAClusterTwoNodeTest extends QpidBrokerTestCase { private static final long RECEIVE_TIMEOUT = 5000l; @@ -83,15 +81,6 @@ public class HAClusterTwoNodeTest extends QpidBrokerTestCase private void startCluster(boolean designedPrimary) throws Exception { setSystemProperty("java.util.logging.config.file", "etc" + File.separator + "log.properties"); - - String storeConfigKeyPrefix = _clusterCreator.getStoreConfigKeyPrefix(); - - setVirtualHostConfigurationProperty(storeConfigKeyPrefix + ".repConfig(0).name", ReplicationConfig.INSUFFICIENT_REPLICAS_TIMEOUT); - setVirtualHostConfigurationProperty(storeConfigKeyPrefix + ".repConfig(0).value", "2 s"); - - setVirtualHostConfigurationProperty(storeConfigKeyPrefix + ".repConfig(1).name", ReplicationConfig.ELECTIONS_PRIMARY_RETRIES); - setVirtualHostConfigurationProperty(storeConfigKeyPrefix + ".repConfig(1).value", "0"); - _clusterCreator.configureClusterNodes(); _clusterCreator.setDesignatedPrimaryOnFirstBroker(designedPrimary); _brokerFailoverUrl = _clusterCreator.getConnectionUrlForAllClusterNodes(); @@ -185,6 +174,12 @@ public class HAClusterTwoNodeTest extends QpidBrokerTestCase assertFalse("Expected node to NOT be set as designated primary", storeBean.getDesignatedPrimary()); storeBean.setDesignatedPrimary(true); + + long limit = System.currentTimeMillis() + 5000; + while( !storeBean.getDesignatedPrimary() && System.currentTimeMillis() < limit) + { + Thread.sleep(100); + } assertTrue("Expected node to now be set as designated primary", storeBean.getDesignatedPrimary()); final Connection connection = getConnection(_brokerFailoverUrl); diff --git a/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HATestClusterCreator.java b/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HATestClusterCreator.java index 353c3a0ec5..4efe1967ce 100644 --- a/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HATestClusterCreator.java +++ b/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HATestClusterCreator.java @@ -19,6 +19,7 @@ */ package org.apache.qpid.server.store.berkeleydb; +import java.io.File; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.HashMap; @@ -26,7 +27,6 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import java.util.TreeMap; import java.util.concurrent.Callable; @@ -38,15 +38,19 @@ import java.util.concurrent.TimeUnit; import javax.jms.Connection; -import org.apache.commons.configuration.XMLConfiguration; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQConnectionURL; -import org.apache.qpid.test.utils.TestBrokerConfiguration; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacadeFactory; import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.test.utils.TestBrokerConfiguration; import org.apache.qpid.url.URLSyntaxException; +import com.sleepycat.je.rep.ReplicationConfig; + public class HATestClusterCreator { protected static final Logger LOGGER = Logger.getLogger(HATestClusterCreator.class); @@ -65,17 +69,14 @@ public class HATestClusterCreator private static final int CONNECTDELAY = 75; private final QpidBrokerTestCase _testcase; - private final Map<Integer, Integer> _brokerPortToBdbPortMap = new HashMap<Integer, Integer>(); - private final Map<Integer, BrokerConfigHolder> _brokerConfigurations = new TreeMap<Integer, BrokerConfigHolder>(); + private final Map<Integer, Integer> _brokerPortToBdbPortMap = new TreeMap<Integer, Integer>(); private final String _virtualHostName; - private final String _vhostStoreConfigKeyPrefix; private final String _ipAddressOfBroker; private final String _groupName ; private final int _numberOfNodes; private int _bdbHelperPort; private int _primaryBrokerPort; - private String _vhostConfigKeyPrefix; public HATestClusterCreator(QpidBrokerTestCase testcase, String virtualHostName, int numberOfNodes) { @@ -84,8 +85,6 @@ public class HATestClusterCreator _groupName = "group" + _testcase.getName(); _ipAddressOfBroker = getIpAddressOfBrokerHost(); _numberOfNodes = numberOfNodes; - _vhostConfigKeyPrefix = "virtualhosts.virtualhost." + _virtualHostName + "."; - _vhostStoreConfigKeyPrefix = _vhostConfigKeyPrefix + "store."; _bdbHelperPort = 0; } @@ -104,13 +103,26 @@ public class HATestClusterCreator _bdbHelperPort = bdbPort; } - configureClusterNode(brokerPort, bdbPort); + String nodeName = getNodeNameForNodeAt(bdbPort); + Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); + messageStoreSettings.put(MessageStore.STORE_PATH, System.getProperty("QPID_WORK") + File.separator + brokerPort); + messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.GROUP_NAME, _groupName); + messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.NODE_NAME, nodeName); + messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.NODE_ADDRESS, getNodeHostPortForNodeAt(bdbPort)); + messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.HELPER_ADDRESS, getHelperHostPort()); + Map<String, String> repSettings = new HashMap<String, String>(); + repSettings.put(ReplicationConfig.INSUFFICIENT_REPLICAS_TIMEOUT, "2 s"); + repSettings.put(ReplicationConfig.ELECTIONS_PRIMARY_RETRIES, "0"); + messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.REPLICATION_CONFIG, repSettings ); + TestBrokerConfiguration brokerConfiguration = _testcase.getBrokerConfiguration(brokerPort); brokerConfiguration.addJmxManagementConfiguration(); - collectConfig(brokerPort, brokerConfiguration, _testcase.getTestVirtualhosts()); + brokerConfiguration.setObjectAttribute(_virtualHostName, VirtualHost.TYPE, BDBHAVirtualHostFactory.TYPE); + brokerConfiguration.setObjectAttribute(_virtualHostName, VirtualHost.MESSAGE_STORE_SETTINGS, messageStoreSettings); brokerPort = _testcase.getNextAvailable(bdbPort + 1); } + _primaryBrokerPort = getPrimaryBrokerPort(); } public void setDesignatedPrimaryOnFirstBroker(boolean designatedPrimary) throws Exception @@ -119,35 +131,27 @@ public class HATestClusterCreator { throw new IllegalArgumentException("Only two nodes groups have the concept of primary"); } - - final Entry<Integer, BrokerConfigHolder> brokerConfigEntry = _brokerConfigurations.entrySet().iterator().next(); - final String configKey = getConfigKey("highAvailability.designatedPrimary"); - brokerConfigEntry.getValue().getTestVirtualhosts().setProperty(configKey, Boolean.toString(designatedPrimary)); - _primaryBrokerPort = brokerConfigEntry.getKey(); + TestBrokerConfiguration config = _testcase.getBrokerConfiguration(_primaryBrokerPort); + @SuppressWarnings("unchecked") + Map<String, Object> storeSetting = (Map<String, Object>) config.getObjectAttributes(_virtualHostName).get(VirtualHost.MESSAGE_STORE_SETTINGS); + storeSetting.put(ReplicatedEnvironmentFacadeFactory.DESIGNATED_PRIMARY, designatedPrimary); + config.setObjectAttribute(_virtualHostName, VirtualHost.MESSAGE_STORE_SETTINGS, storeSetting); + config.setSaved(false); } - /** - * @param configKeySuffix "highAvailability.designatedPrimary", for example - * @return "virtualhost.test.store.highAvailability.designatedPrimary", for example - */ - private String getConfigKey(String configKeySuffix) + private int getPrimaryBrokerPort() { - final String configKey = StringUtils.substringAfter(_vhostStoreConfigKeyPrefix + configKeySuffix, "virtualhosts."); - return configKey; + return _brokerPortToBdbPortMap.keySet().iterator().next(); } public void startNode(final int brokerPortNumber) throws Exception { - final BrokerConfigHolder brokerConfigHolder = _brokerConfigurations.get(brokerPortNumber); - - _testcase.setTestVirtualhosts(brokerConfigHolder.getTestVirtualhosts()); - _testcase.startBroker(brokerPortNumber); } public void startCluster() throws Exception { - for (final Integer brokerPortNumber : _brokerConfigurations.keySet()) + for (final Integer brokerPortNumber : _brokerPortToBdbPortMap.keySet()) { startNode(brokerPortNumber); } @@ -155,21 +159,20 @@ public class HATestClusterCreator public void startClusterParallel() throws Exception { - final ExecutorService executor = Executors.newFixedThreadPool(_brokerConfigurations.size()); + final ExecutorService executor = Executors.newFixedThreadPool(_brokerPortToBdbPortMap.size()); try { List<Future<Object>> brokers = new CopyOnWriteArrayList<Future<Object>>(); - for (final Integer brokerPortNumber : _brokerConfigurations.keySet()) + for (final Integer brokerPortNumber : _brokerPortToBdbPortMap.keySet()) { - final BrokerConfigHolder brokerConfigHolder = _brokerConfigurations.get(brokerPortNumber); + final TestBrokerConfiguration brokerConfig = _testcase.getBrokerConfiguration(brokerPortNumber); Future<Object> future = executor.submit(new Callable<Object>() { public Object call() { try { - _testcase.startBroker(brokerPortNumber, brokerConfigHolder.getTestConfiguration(), - brokerConfigHolder.getTestVirtualhosts()); + _testcase.startBroker(brokerPortNumber, brokerConfig); return "OK"; } catch (Exception e) @@ -213,7 +216,7 @@ public class HATestClusterCreator public void stopCluster() throws Exception { - for (final Integer brokerPortNumber : _brokerConfigurations.keySet()) + for (final Integer brokerPortNumber : _brokerPortToBdbPortMap.keySet()) { try { @@ -345,22 +348,9 @@ public class HATestClusterCreator public Set<Integer> getBrokerPortNumbersForNodes() { - return new HashSet<Integer>(_brokerConfigurations.keySet()); + return new HashSet<Integer>(_brokerPortToBdbPortMap.keySet()); } - private void configureClusterNode(final int brokerPort, final int bdbPort) throws Exception - { - final String nodeName = getNodeNameForNodeAt(bdbPort); - - - _testcase.setVirtualHostConfigurationProperty(_vhostConfigKeyPrefix + "type", BDBHAVirtualHostFactory.TYPE); - _testcase.setVirtualHostConfigurationProperty(_vhostStoreConfigKeyPrefix + "class", "org.apache.qpid.server.store.berkeleydb.BDBHAMessageStore"); - - _testcase.setVirtualHostConfigurationProperty(_vhostStoreConfigKeyPrefix + "highAvailability.groupName", _groupName); - _testcase.setVirtualHostConfigurationProperty(_vhostStoreConfigKeyPrefix + "highAvailability.nodeName", nodeName); - _testcase.setVirtualHostConfigurationProperty(_vhostStoreConfigKeyPrefix + "highAvailability.nodeHostPort", getNodeHostPortForNodeAt(bdbPort)); - _testcase.setVirtualHostConfigurationProperty(_vhostStoreConfigKeyPrefix + "highAvailability.helperHostPort", getHelperHostPort()); - } public String getIpAddressOfBrokerHost() { @@ -375,55 +365,19 @@ public class HATestClusterCreator } } - private void collectConfig(final int brokerPortNumber, TestBrokerConfiguration testConfiguration, XMLConfiguration testVirtualhosts) - { - _brokerConfigurations.put(brokerPortNumber, new BrokerConfigHolder(testConfiguration, - (XMLConfiguration) testVirtualhosts.clone())); - } - - public class BrokerConfigHolder - { - private final TestBrokerConfiguration _testConfiguration; - private final XMLConfiguration _testVirtualhosts; - - public BrokerConfigHolder(TestBrokerConfiguration testConfiguration, XMLConfiguration testVirtualhosts) - { - _testConfiguration = testConfiguration; - _testVirtualhosts = testVirtualhosts; - } - - public TestBrokerConfiguration getTestConfiguration() - { - return _testConfiguration; - } - - public XMLConfiguration getTestVirtualhosts() - { - return _testVirtualhosts; - } - } - public void modifyClusterNodeBdbAddress(int brokerPortNumberToBeMoved, int newBdbPort) { - final BrokerConfigHolder brokerConfigHolder = _brokerConfigurations.get(brokerPortNumberToBeMoved); - final XMLConfiguration virtualHostConfig = brokerConfigHolder.getTestVirtualhosts(); - - final String configKey = getConfigKey("highAvailability.nodeHostPort"); - final String oldBdbHostPort = virtualHostConfig.getString(configKey); - - final String[] oldHostAndPort = StringUtils.split(oldBdbHostPort, ":"); - final String oldHost = oldHostAndPort[0]; - - final String newBdbHostPort = oldHost + ":" + newBdbPort; - - virtualHostConfig.setProperty(configKey, newBdbHostPort); - collectConfig(brokerPortNumberToBeMoved, brokerConfigHolder.getTestConfiguration(), virtualHostConfig); + TestBrokerConfiguration config = _testcase.getBrokerConfiguration(brokerPortNumberToBeMoved); + + @SuppressWarnings("unchecked") + Map<String, Object> storeSetting = (Map<String, Object>) config.getObjectAttributes(_virtualHostName).get(VirtualHost.MESSAGE_STORE_SETTINGS); + String oldBdbHostPort = (String) storeSetting.get(ReplicatedEnvironmentFacadeFactory.NODE_ADDRESS); + String[] oldHostAndPort = StringUtils.split(oldBdbHostPort, ":"); + String oldHost = oldHostAndPort[0]; + String newBdbHostPort = oldHost + ":" + newBdbPort; + storeSetting.put(ReplicatedEnvironmentFacadeFactory.NODE_ADDRESS, newBdbHostPort); + config.setObjectAttribute(_virtualHostName, VirtualHost.MESSAGE_STORE_SETTINGS, storeSetting); + config.setSaved(false); } - public String getStoreConfigKeyPrefix() - { - return _vhostStoreConfigKeyPrefix; - } - - } diff --git a/qpid/java/broker-core/pom.xml b/qpid/java/broker-core/pom.xml index a26e781da4..fa51ad0b7d 100644 --- a/qpid/java/broker-core/pom.xml +++ b/qpid/java/broker-core/pom.xml @@ -60,28 +60,7 @@ <artifactId>slf4j-log4j12</artifactId> </dependency> - <dependency> - <groupId>commons-logging</groupId> - <artifactId>commons-logging</artifactId> - </dependency> - - <dependency> - <groupId>commons-beanutils</groupId> - <artifactId>commons-beanutils-core</artifactId> - </dependency> - - <dependency> - <groupId>commons-digester</groupId> - <artifactId>commons-digester</artifactId> - <exclusions> - <exclusion> - <groupId>commons-beanutils</groupId> - <artifactId>commons-beanutils</artifactId> - </exclusion> - </exclusions> - </dependency> - - <dependency> + <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> </dependency> @@ -92,16 +71,6 @@ </dependency> <dependency> - <groupId>commons-collections</groupId> - <artifactId>commons-collections</artifactId> - </dependency> - - <dependency> - <groupId>commons-configuration</groupId> - <artifactId>commons-configuration</artifactId> - </dependency> - - <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-core-asl</artifactId> </dependency> diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java deleted file mode 100644 index 8f77de56b8..0000000000 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * - * 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.configuration; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.Map; -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; - -import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.server.configuration.plugins.AbstractConfiguration; - -import java.util.List; - -public class QueueConfiguration extends AbstractConfiguration -{ - private String _name; - private VirtualHostConfiguration _vHostConfig; - - public QueueConfiguration(String name, VirtualHostConfiguration virtualHostConfiguration) throws ConfigurationException - { - _vHostConfig = virtualHostConfiguration; - _name = name; - - CompositeConfiguration mungedConf = new CompositeConfiguration(); - mungedConf.addConfiguration(_vHostConfig.getConfig().subset("queues.queue." + escapeTagName(name))); - - setConfiguration("virtualhosts.virtualhost.queues.queue", mungedConf); - } - - public String[] getElementsProcessed() - { - return new String[]{"maximumMessageSize", - "maximumQueueDepth", - "maximumMessageCount", - "maximumMessageAge", - "minimumAlertRepeatGap", - "durable", - "exchange", - "exclusive", - "queue", - "autodelete", - "priority", - "priorities", - "routingKey", - "capacity", - "flowResumeCapacity", - "lvq", - "lvqKey", - "sortKey", - "maximumDeliveryCount", - "deadLetterQueues", - "argument" - }; - } - - @Override - public void validateConfiguration() throws ConfigurationException - { - //Currently doesn't do validation - } - - public VirtualHostConfiguration getVirtualHostConfiguration() - { - return _vHostConfig; - } - - private boolean getDefaultedBoolean(String attribute) - { - final Configuration config = _vHostConfig.getConfig(); - if(config.containsKey("queues."+attribute)) - { - final boolean defaultValue = config.getBoolean("queues." + attribute); - return getBooleanValue(attribute, defaultValue); - } - else - { - return getBooleanValue(attribute); - } - } - - public boolean getDurable() - { - return getDefaultedBoolean("durable"); - } - - public boolean getExclusive() - { - return getDefaultedBoolean("exclusive"); - } - - public boolean getAutoDelete() - { - return getDefaultedBoolean("autodelete"); - } - - public String getOwner() - { - return getStringValue("owner", null); - } - - public boolean getPriority() - { - return getDefaultedBoolean("priority"); - } - - public int getPriorities() - { - final Configuration config = _vHostConfig.getConfig(); - - int defaultValue; - if(config.containsKey("queues.priorities")) - { - defaultValue = config.getInt("queues.priorities"); - } - else - { - defaultValue = -1; - } - return getIntValue("priorities", defaultValue); - } - - public String getExchange() - { - final Configuration config = _vHostConfig.getConfig(); - - String defaultValue; - - if(config.containsKey("queues.exchange")) - { - defaultValue = config.getString("queues.exchange"); - } - else - { - defaultValue = ""; - } - - return getStringValue("exchange", defaultValue); - } - - public List getRoutingKeys() - { - return getListValue("routingKey"); - } - - public String getName() - { - return _name; - } - - public String getDescription() - { - return getStringValue("description"); - } - - public int getMaximumMessageAge() - { - return getIntValue("maximumMessageAge"); - } - - public long getMaximumQueueDepth() - { - return getLongValue("maximumQueueDepth"); - } - - public long getMaximumMessageSize() - { - return getLongValue("maximumMessageSize"); - } - - public long getMaximumMessageCount() - { - return getLongValue("maximumMessageCount"); - } - - public long getMinimumAlertRepeatGap() - { - return getLongValue("minimumAlertRepeatGap"); - } - - public long getCapacity() - { - return getLongValue("capacity"); - } - - public long getFlowResumeCapacity() - { - return getLongValue("flowResumeCapacity"); - } - - public boolean isLVQ() - { - return getBooleanValue("lvq"); - } - - public String getLVQKey() - { - return getStringValue("lvqKey", null); - } - - public String getQueueSortKey() - { - return getStringValue("sortKey", null); - } - - public int getMaxDeliveryCount() - { - return getIntValue("maximumDeliveryCount", _vHostConfig.getMaxDeliveryCount()); - } - - /** - * Check if dead letter queue delivery is enabled, deferring to the virtualhost configuration if not set. - */ - public boolean isDeadLetterQueueEnabled() - { - return getBooleanValue("deadLetterQueues", _vHostConfig.isDeadLetterQueueEnabled()); - } - - public Map<String,String> getArguments() - { - return getMap("argument"); - } - - public Map<String,String> getBindingArguments(String routingKey) - { - - return getConfig().containsKey(routingKey+".bindingArgument") ? getMap(routingKey+".bindingArgument") : null; - } -} diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java deleted file mode 100644 index 189f5916e0..0000000000 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java +++ /dev/null @@ -1,301 +0,0 @@ -/* - * - * 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.configuration; - -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; - -import org.apache.qpid.server.configuration.plugins.AbstractConfiguration; -import org.apache.qpid.server.model.Broker; - -import java.io.File; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -public class VirtualHostConfiguration extends AbstractConfiguration -{ - private final String _name; - private final Map<String, QueueConfiguration> _queues = new HashMap<String, QueueConfiguration>(); - private final Map<String, ExchangeConfiguration> _exchanges = new HashMap<String, ExchangeConfiguration>(); - private final Broker _broker; - private final long _defaultHouseKeepingCheckPeriod; - - public VirtualHostConfiguration(String name, Configuration config, Broker broker) throws ConfigurationException - { - _name = name; - _broker = broker; - - // store value of this attribute for running life of virtual host since updating of this value has no run-time effect - _defaultHouseKeepingCheckPeriod = ((Number)_broker.getAttribute(Broker.VIRTUALHOST_HOUSEKEEPING_CHECK_PERIOD)).longValue(); - setConfiguration(config); - } - - public VirtualHostConfiguration(String name, File configurationFile, Broker broker) throws ConfigurationException - { - this(name, loadConfiguration(name, configurationFile), broker); - } - - private static Configuration loadConfiguration(String name, File configurationFile) throws ConfigurationException - { - Configuration configuration = null; - if (configurationFile == null) - { - throw new IllegalConfigurationException("Virtualhost configuration file must be supplied!"); - } - else - { - Configuration virtualHostConfig = XmlConfigurationUtilities.parseConfig(configurationFile); - - // check for the element with the same name as virtual host - Configuration config = virtualHostConfig.subset("virtualhost." + XmlConfigurationUtilities.escapeTagName(name)); - if (config.isEmpty()) - { - throw new IllegalConfigurationException("No configuration found for virtual host '" + name + "' in " + configurationFile.getAbsolutePath()); - } - else - { - configuration = config; - } - } - return configuration; - } - - /** - * Apply the given configuration to this VirtualHostConfiguration - * - * @param config the config to apply - * @throws ConfigurationException if a problem occurs with configuration - */ - public void setConfiguration(Configuration config) throws ConfigurationException - { - setConfiguration("virtualhosts.virtualhost", config); - - Iterator i = getListValue("queues.queue.name").iterator(); - - while (i.hasNext()) - { - String queueName = (String) i.next(); - _queues.put(queueName, new QueueConfiguration(queueName, this)); - } - - i = getListValue("exchanges.exchange.name").iterator(); - int count = 0; - while (i.hasNext()) - { - CompositeConfiguration mungedConf = new CompositeConfiguration(); - mungedConf.addConfiguration(config.subset("exchanges.exchange(" + count++ + ")")); - mungedConf.addConfiguration(getConfig().subset("exchanges")); - String exchName = (String) i.next(); - _exchanges.put(exchName, new ExchangeConfiguration(exchName, mungedConf)); - } - } - - public String getName() - { - return _name; - } - - public long getHousekeepingCheckPeriod() - { - return getLongValue("housekeeping.checkPeriod", _defaultHouseKeepingCheckPeriod); - } - - public Configuration getStoreConfiguration() - { - return getConfig().subset("store"); - } - - public String getMessageStoreClass() - { - return getStringValue("store.class", null); - } - - public void setMessageStoreClass(String storeFactoryClass) - { - getConfig().setProperty("store.class", storeFactoryClass); - } - - public List getExchanges() - { - return getListValue("exchanges.exchange.name"); - } - - public String[] getQueueNames() - { - return _queues.keySet().toArray(new String[_queues.size()]); - } - - public ExchangeConfiguration getExchangeConfiguration(String exchangeName) - { - return _exchanges.get(exchangeName); - } - - public QueueConfiguration getQueueConfiguration(String queueName) - { - // We might be asked for the config for a queue we don't know about, - // such as one that's been dynamically created. Those get the defaults by default. - if (_queues.containsKey(queueName)) - { - return _queues.get(queueName); - } - else - { - try - { - return new QueueConfiguration(queueName, this); - } - catch (ConfigurationException e) - { - // The configuration is empty so there can't be an error. - return null; - } - } - } - - public int getMaximumMessageAge() - { - return getIntValue("queues.maximumMessageAge", getBrokerAttributeAsInt(Broker.QUEUE_ALERT_THRESHOLD_MESSAGE_AGE)); - } - - public Long getMaximumQueueDepth() - { - return getLongValue("queues.maximumQueueDepth", getBrokerAttributeAsLong(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_BYTES)); - } - - public Long getMaximumMessageSize() - { - return getLongValue("queues.maximumMessageSize", getBrokerAttributeAsLong(Broker.QUEUE_ALERT_THRESHOLD_MESSAGE_SIZE)); - } - - public Long getMaximumMessageCount() - { - return getLongValue("queues.maximumMessageCount", getBrokerAttributeAsLong(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES)); - } - - public Long getMinimumAlertRepeatGap() - { - return getLongValue("queues.minimumAlertRepeatGap", getBrokerAttributeAsLong(Broker.QUEUE_ALERT_REPEAT_GAP)); - } - - public long getCapacity() - { - return getLongValue("queues.capacity", getBrokerAttributeAsLong(Broker.QUEUE_FLOW_CONTROL_SIZE_BYTES)); - } - - public long getFlowResumeCapacity() - { - return getLongValue("queues.flowResumeCapacity", getBrokerAttributeAsLong(Broker.QUEUE_FLOW_CONTROL_RESUME_SIZE_BYTES)); - } - - public String[] getElementsProcessed() - { - return new String[]{"queues", "exchanges", "custom-exchanges", "store", "housekeeping"}; - - } - - @Override - public void validateConfiguration() throws ConfigurationException - { - // QPID-3249. Support for specifying authentication name at vhost level is no longer supported. - if (getListValue("security.authentication.name").size() > 0) - { - String message = "Validation error : security/authentication/name is no longer a supported element within the configuration xml." - + " It appears in virtual host definition : " + _name; - throw new ConfigurationException(message); - } - - // QPID-3266. Tidy up housekeeping configuration option for scheduling frequency - if (contains("housekeeping.expiredMessageCheckPeriod")) - { - String message = "Validation error : housekeeping/expiredMessageCheckPeriod must be replaced by housekeeping/checkPeriod." - + " It appears in virtual host definition : " + _name; - throw new ConfigurationException(message); - } - } - - public int getHouseKeepingThreadCount() - { - return getIntValue("housekeeping.poolSize", Runtime.getRuntime().availableProcessors()); - } - - public long getTransactionTimeoutOpenWarn() - { - return getLongValue("transactionTimeout.openWarn", - getBrokerAttributeAsLong(Broker.VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_WARN)); - } - - public long getTransactionTimeoutOpenClose() - { - return getLongValue("transactionTimeout.openClose", - getBrokerAttributeAsLong(Broker.VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE)); - } - - public long getTransactionTimeoutIdleWarn() - { - return getLongValue("transactionTimeout.idleWarn", - getBrokerAttributeAsLong(Broker.VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_WARN)); - } - - public long getTransactionTimeoutIdleClose() - { - return getLongValue("transactionTimeout.idleClose", - getBrokerAttributeAsLong(Broker.VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE)); - } - - public int getMaxDeliveryCount() - { - return getIntValue("queues.maximumDeliveryCount", getBrokerAttributeAsInt(Broker.QUEUE_MAXIMUM_DELIVERY_ATTEMPTS)); - } - - /** - * Check if dead letter queue delivery is enabled, deferring to the broker configuration if not set. - */ - public boolean isDeadLetterQueueEnabled() - { - return getBooleanValue("queues.deadLetterQueues", getBrokerAttributeAsBoolean(Broker.QUEUE_DEAD_LETTER_QUEUE_ENABLED)); - } - - private long getBrokerAttributeAsLong(String name) - { - Number brokerValue = (Number)_broker.getAttribute(name); - return brokerValue == null? 0 : brokerValue.longValue(); - } - - private int getBrokerAttributeAsInt(String name) - { - Number brokerValue = (Number)_broker.getAttribute(name); - return brokerValue == null? 0 : brokerValue.intValue(); - } - - private boolean getBrokerAttributeAsBoolean(String name) - { - Boolean brokerValue = (Boolean)_broker.getAttribute(name); - return brokerValue == null? false : brokerValue.booleanValue(); - } - - public String getType() - { - return getStringValue("type", "org.apache.qpid.server.store.berkeleydb.BDBHAMessageStore".equals(getMessageStoreClass()) ? "BDB_HA": "STANDARD"); - } -} diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/XmlConfigurationUtilities.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/XmlConfigurationUtilities.java deleted file mode 100644 index 84972c1e0a..0000000000 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/XmlConfigurationUtilities.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * - * 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.configuration; - -import java.io.File; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.ConfigurationFactory; -import org.apache.commons.configuration.SystemConfiguration; -import org.apache.commons.configuration.XMLConfiguration; - -public class XmlConfigurationUtilities -{ - - // Our configuration class needs to make the interpolate method - // public so it can be called below from the config method. - public static class MyConfiguration extends CompositeConfiguration - { - public String interpolate(String obj) - { - return super.interpolate(obj); - } - } - - public static Configuration parseConfig(File file) throws ConfigurationException - { - ConfigurationFactory factory = new ConfigurationFactory(); - factory.setConfigurationFileName(file.getAbsolutePath()); - Configuration conf = factory.getConfiguration(); - - Iterator<?> keys = conf.getKeys(); - if (!keys.hasNext()) - { - keys = null; - conf = flatConfig(file); - } - - return conf; - } - - public final static Configuration flatConfig(File file) throws ConfigurationException - { - // We have to override the interpolate methods so that - // interpolation takes place across the entirety of the - // composite configuration. Without doing this each - // configuration object only interpolates variables defined - // inside itself. - final MyConfiguration conf = new MyConfiguration(); - conf.addConfiguration(new SystemConfiguration() - { - protected String interpolate(String o) - { - return conf.interpolate(o); - } - }); - conf.addConfiguration(new XMLConfiguration(file) - { - protected String interpolate(String o) - { - return conf.interpolate(o); - } - }); - return conf; - } - - public static String escapeTagName(String name) - { - return name.replaceAll("\\.", "\\.\\."); - } -} diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/plugins/AbstractConfiguration.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/plugins/AbstractConfiguration.java deleted file mode 100644 index c28ea726c0..0000000000 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/plugins/AbstractConfiguration.java +++ /dev/null @@ -1,344 +0,0 @@ -/* - * 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.configuration.plugins; - -import java.util.LinkedHashMap; -import java.util.Map; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.ConversionException; -import org.apache.log4j.Logger; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Set; - -public abstract class AbstractConfiguration -{ - protected static final Logger _logger = Logger.getLogger(AbstractConfiguration.class); - - private Configuration _config; - - /** - * The Elements that this Plugin can process. - * - * For a Queues plugin that would be a list containing: - * <ul> - * <li>queue - the queue entries - * <li>the alerting values for defaults - * <li>exchange - the default exchange - * <li>durable - set the default durability - * </ul> - */ - abstract public String[] getElementsProcessed(); - - /** Performs configuration validation. */ - public void validateConfiguration() throws ConfigurationException - { - // Override in sub-classes - } - - public Configuration getConfig() - { - return _config; - } - - /** - * Sets the configuration for this plugin - * - * @param path - * @param configuration the configuration for this plugin. - */ - public void setConfiguration(String path, Configuration configuration) throws ConfigurationException - { - _config = configuration; - - // Extract a list of elements for processing - Iterator<?> keys = configuration.getKeys(); - - Set<String> elements = new HashSet<String>(); - while (keys.hasNext()) - { - String key = (String) keys.next(); - - int elementNameIndex = key.indexOf("."); - - String element = key.trim(); - if (elementNameIndex != -1) - { - element = key.substring(0, elementNameIndex).trim(); - } - - // Trim any element properties - elementNameIndex = element.indexOf("["); - if (elementNameIndex > 0) - { - element = element.substring(0, elementNameIndex).trim(); - } - - elements.add(element); - } - - //Remove the items we already expect in the configuration - for (String tag : getElementsProcessed()) - { - - // Work round the issue with Commons configuration. - // With an XMLConfiguration the key will be [@property] - // but with a CompositeConfiguration it will be @property]. - // Hide this issue from our users so when/if we change the - // configuration they don't have to. - int bracketIndex = tag.indexOf("["); - if (bracketIndex != -1) - { - tag = tag.substring(bracketIndex + 1, tag.length()); - } - - elements.remove(tag); - } - - if (_logger.isInfoEnabled()) - { - if (!elements.isEmpty()) - { - _logger.info("Elements to lookup:" + path); - for (String tag : elements) - { - _logger.info("Tag:'" + tag + "'"); - } - } - } - - validateConfiguration(); - } - - /** Helper method to print out list of keys in a {@link Configuration}. */ - public static final void showKeys(Configuration config) - { - if (config.isEmpty()) - { - _logger.info("Configuration is empty"); - } - else - { - Iterator<?> keys = config.getKeys(); - while (keys.hasNext()) - { - String key = (String) keys.next(); - _logger.info("Configuration key: " + key); - } - } - } - - protected boolean hasConfiguration() - { - return _config != null; - } - - /// Getters - - protected double getDoubleValue(String property) - { - return getDoubleValue(property, 0.0); - } - - protected double getDoubleValue(String property, double defaultValue) - { - return _config.getDouble(property, defaultValue); - } - - protected long getLongValue(String property) - { - return getLongValue(property, 0); - } - - protected long getLongValue(String property, long defaultValue) - { - return _config.getLong(property, defaultValue); - } - - protected int getIntValue(String property) - { - return getIntValue(property, 0); - } - - protected int getIntValue(String property, int defaultValue) - { - return _config.getInt(property, defaultValue); - } - - protected String getStringValue(String property) - { - return getStringValue(property, null); - } - - protected String getStringValue(String property, String defaultValue) - { - return _config.getString(property, defaultValue); - } - - protected boolean getBooleanValue(String property) - { - return getBooleanValue(property, false); - } - - protected boolean getBooleanValue(String property, boolean defaultValue) - { - return _config.getBoolean(property, defaultValue); - } - - protected List getListValue(String property) - { - return getListValue(property, Collections.EMPTY_LIST); - } - - protected List getListValue(String property, List defaultValue) - { - return _config.getList(property, defaultValue); - } - - /// Validation Helpers - - protected boolean contains(String property) - { - return _config.getProperty(property) != null; - } - - /** - * Provide mechanism to validate Configuration contains a Positive Long Value - * - * @param property - * - * @throws ConfigurationException - */ - protected void validatePositiveLong(String property) throws ConfigurationException - { - try - { - if (!containsPositiveLong(property)) - { - throw new ConfigurationException(this.getClass().getSimpleName() - + ": '" + property + - "' must be a Positive Long value."); - } - } - catch (Exception e) - { - Throwable last = e; - - // Find the first cause - if (e instanceof ConversionException) - { - Throwable t = e.getCause(); - while (t != null) - { - last = t; - t = last.getCause(); - } - } - - throw new ConfigurationException(this.getClass().getSimpleName() + - ": unable to configure invalid " + - property + ":" + - _config.getString(property), - last); - } - } - - protected boolean containsLong(String property) - { - try - { - _config.getLong(property); - return true; - } - catch (NoSuchElementException e) - { - return false; - } - } - - protected boolean containsPositiveLong(String property) - { - try - { - long value = _config.getLong(property); - return value > 0; - } - catch (NoSuchElementException e) - { - return false; - } - - } - - protected boolean containsInt(String property) - { - try - { - _config.getInt(property); - return true; - } - catch (NoSuchElementException e) - { - return false; - } - } - - protected boolean containsBoolean(String property) - { - try - { - _config.getBoolean(property); - return true; - } - catch (NoSuchElementException e) - { - return false; - } - } - - public static String escapeTagName(String name) - { - return name.replaceAll("\\.", "\\.\\."); - } - - protected void setConfig(Configuration config) - { - _config = config; - } - - protected Map<String,String> getMap(String name) - { - List elements = getListValue(name,Collections.emptyList()); - - Map<String,String> map = new LinkedHashMap(); - for(Object item : elements) - { - String[] keyValue = String.valueOf(item).split("=",2); - map.put(keyValue[0].trim(), keyValue.length > 1 ? keyValue[1].trim() : null); - } - return map; - } -} - - diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/PreferencesProviderRecoverer.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/PreferencesProviderRecoverer.java index db3f968435..3953f6c91d 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/PreferencesProviderRecoverer.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/PreferencesProviderRecoverer.java @@ -41,7 +41,7 @@ public class PreferencesProviderRecoverer implements ConfiguredObjectRecoverer<P AuthenticationProvider authenticationProvider = RecovererHelper.verifyOnlyParentIsOfType(AuthenticationProvider.class, parents); Map<String, Object> attributes = entry.getAttributes(); String type = MapValueConverter.getStringAttribute(PreferencesProvider.TYPE, attributes); - PreferencesProviderFactory factory = PreferencesProviderFactory.FACTORIES.get(type); + PreferencesProviderFactory factory = PreferencesProviderFactory.FACTORY_LOADER.get(type); return factory.createInstance(entry.getId(), attributes, authenticationProvider); } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/StoreUpgrader.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/StoreUpgrader.java index 124584e99c..1cadf270d7 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/StoreUpgrader.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/StoreUpgrader.java @@ -1,4 +1,4 @@ -package org.apache.qpid.server.configuration.startup;/* +/* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -19,10 +19,13 @@ package org.apache.qpid.server.configuration.startup;/* * */ +package org.apache.qpid.server.configuration.startup; + import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; + import org.apache.qpid.server.configuration.ConfigurationEntry; import org.apache.qpid.server.configuration.ConfigurationEntryStore; import org.apache.qpid.server.model.Broker; @@ -30,6 +33,7 @@ import org.apache.qpid.server.model.Broker; public abstract class StoreUpgrader { + private static Map<String, StoreUpgrader> _upgraders = new HashMap<String, StoreUpgrader>(); // Note: don't use externally defined constants in upgraders in case they change, the values here MUST stay the same @@ -134,7 +138,9 @@ public abstract class StoreUpgrader } }; - private StoreUpgrader(String version) + final static StoreUpgrader UPGRADE_1_3 = new StoreUpgrader1_3("1.3"); + + protected StoreUpgrader(String version) { _upgraders.put(version, this); } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/StoreUpgrader1_3.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/StoreUpgrader1_3.java new file mode 100644 index 0000000000..913ed4d773 --- /dev/null +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/StoreUpgrader1_3.java @@ -0,0 +1,345 @@ +/* + * + * 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.configuration.startup; + +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.Map; +import java.util.Set; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfigurationEntryStore; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.model.Broker; + +@SuppressWarnings("serial") +public final class StoreUpgrader1_3 extends StoreUpgrader +{ + public static final String VERSION = "1.3"; + + private Map<String, VirtualHostEntryUpgrader> _vhostUpgraderMap = new HashMap<String, VirtualHostEntryUpgrader>() + {{ + put("BDB_HA", new BdbHaVirtualHostUpgrader()); + put("STANDARD", new StandardVirtualHostUpgrader()); + }}; + + StoreUpgrader1_3(String version) + { + super(version); + } + + @Override + protected void doUpgrade(ConfigurationEntryStore store) + { + ConfigurationEntry root = store.getRootEntry(); + Map<String, Collection<ConfigurationEntry>> children = root.getChildren(); + Collection<ConfigurationEntry> vhosts = children.get("VirtualHost"); + Collection<ConfigurationEntry> changed = new ArrayList<ConfigurationEntry>(); + + for (ConfigurationEntry vhost : vhosts) + { + Map<String, Object> attributes = vhost.getAttributes(); + if (attributes.containsKey("configPath")) + { + throw new IllegalConfigurationException("Auto-upgrade of virtual host " + attributes.get("name") + " having XML configuration is not supported. Virtual host configuration file is " + attributes.get("configPath")); + } + + String type = (String) attributes.get("type"); + VirtualHostEntryUpgrader vhostUpgrader = _vhostUpgraderMap.get(type); + if (vhostUpgrader == null) + { + throw new IllegalConfigurationException("Don't know how to perform an upgrade from version " + VERSION + + " for virtualhost type " + type); + } + ConfigurationEntry newVirtualHostConfigurationEntry = vhostUpgrader.upgrade(store, vhost); + changed.add(newVirtualHostConfigurationEntry); + } + + Map<String, Object> attributes = new HashMap<String, Object>(root.getAttributes()); + attributes.put(Broker.MODEL_VERSION, "1.4"); + changed.add(new ConfigurationEntry(root.getId(), root.getType(), attributes, root.getChildrenIds(), store)); + store.save(changed.toArray(new ConfigurationEntry[changed.size()])); + } + + public interface VirtualHostEntryUpgrader + { + ConfigurationEntry upgrade(ConfigurationEntryStore store, ConfigurationEntry vhost); + } + + public class BdbHaVirtualHostUpgrader implements VirtualHostEntryUpgrader + { + private final String[] HA_ATTRIBUTES = + { "storePath", "haNodeName", "haGroupName", "haHelperAddress", "haCoalescingSync", "haNodeAddress", "haDurability", + "haDesignatedPrimary", "haReplicationConfig", "bdbEnvironmentConfig" }; + + @Override + public ConfigurationEntry upgrade(ConfigurationEntryStore store, ConfigurationEntry vhost) + { + Map<String, Object> attributes = vhost.getAttributes(); + Map<String, Object> newAttributes = new HashMap<String, Object>(attributes); + Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); + + for (String haAttribute : HA_ATTRIBUTES) + { + if (attributes.containsKey(haAttribute)) + { + messageStoreSettings.put(haAttribute, newAttributes.remove(haAttribute)); + } + } + + if (attributes.containsKey("storeUnderfullSize")) + { + messageStoreSettings.put("storeUnderfullSize", newAttributes.remove("storeUnderfullSize")); + } + if (attributes.containsKey("storeOverfullSize")) + { + messageStoreSettings.put("storeOverfullSize", newAttributes.remove("storeOverfullSize")); + } + newAttributes.remove("storeType"); + newAttributes.put("messageStoreSettings", messageStoreSettings); + return new ConfigurationEntry(vhost.getId(), vhost.getType(), newAttributes, vhost.getChildrenIds(), store); + } + + } + + public interface StoreEntryUpgrader + { + Map<String, Object> upgrade(Map<String, Object> attributes); + + Set<String> getNamesToBeDeleted(); + } + + public class GenericMessageStoreEntryUpgrader implements StoreEntryUpgrader + { + private Map<String, String> _oldToNewNamesMap; + private String _storeType; + + public GenericMessageStoreEntryUpgrader(String storeType, Map<String, String> oldToNewNamesMap) + { + _oldToNewNamesMap = oldToNewNamesMap; + _storeType = storeType; + } + + @Override + public Map<String, Object> upgrade(Map<String, Object> attributes) + { + Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); + for (Map.Entry<String, String> nameMapEntry : _oldToNewNamesMap.entrySet()) + { + String attributeName = nameMapEntry.getKey(); + if (attributes.containsKey(attributeName)) + { + messageStoreSettings.put(nameMapEntry.getValue(), attributes.get(attributeName)); + } + } + messageStoreSettings.put("storeType", _storeType); + return messageStoreSettings; + } + + @Override + public Set<String> getNamesToBeDeleted() + { + Set<String> names = new HashSet<String>(_oldToNewNamesMap.keySet()); + names.add("storeType"); + return names; + } + + } + + public class JDBCMessageStoreEntryUpgrader implements StoreEntryUpgrader + { + private final String[] JDBC_ATTRIBUTES = + { "connectionURL", "connectionPool", "jdbcBigIntType", "jdbcBytesForBlob", "jdbcVarbinaryType", "jdbcBlobType", + "partitionCount", "maxConnectionsPerPartition", "minConnectionsPerPartition" }; + + @Override + public Map<String, Object> upgrade(Map<String, Object> attributes) + { + Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); + + if (attributes.containsKey("storePath")) + { + messageStoreSettings.put("connectionURL", attributes.get("storePath")); + } + + copyJdbcStoreSettings(attributes, messageStoreSettings); + + messageStoreSettings.put("storeType", "JDBC"); + return messageStoreSettings; + } + + @Override + public Set<String> getNamesToBeDeleted() + { + Set<String> names = new HashSet<String>(); + names.addAll(Arrays.asList(JDBC_ATTRIBUTES)); + names.add("storePath"); + names.add("storeType"); + return names; + } + + private void copyJdbcStoreSettings(Map<String, Object> attributes, Map<String, Object> messageStoreSettings) + { + for (String jdbcAttribute : JDBC_ATTRIBUTES) + { + if (attributes.containsKey(jdbcAttribute)) + { + messageStoreSettings.put(jdbcAttribute, attributes.get(jdbcAttribute)); + } + } + } + + } + + public class JDBCConfigurationStoreEntryUpgrader implements StoreEntryUpgrader + { + + private final String[] JDBC_ATTRIBUTES = + { "connectionPool", "jdbcBigIntType", "jdbcBytesForBlob", "jdbcVarbinaryType", "jdbcBlobType", "partitionCount", + "maxConnectionsPerPartition", "minConnectionsPerPartition" }; + + @Override + public Map<String, Object> upgrade(Map<String, Object> attributes) + { + Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); + + if (attributes.containsKey("configStorePath")) + { + messageStoreSettings.put("connectionURL", attributes.get("configStorePath")); + } + + if (attributes.containsKey("configConnectionURL")) + { + messageStoreSettings.put("connectionURL", attributes.get("configConnectionURL")); + } + + copyJdbcStoreSettings(attributes, messageStoreSettings); + + messageStoreSettings.put("storeType", "JDBC"); + return messageStoreSettings; + } + + @Override + public Set<String> getNamesToBeDeleted() + { + Set<String> names = new HashSet<String>(); + names.addAll(Arrays.asList(JDBC_ATTRIBUTES)); + names.add("configStorePath"); + names.add("configStoreType"); + names.add("configConnectionURL"); + return names; + } + + private void copyJdbcStoreSettings(Map<String, Object> attributes, Map<String, Object> messageStoreSettings) + { + for (String jdbcAttribute : JDBC_ATTRIBUTES) + { + if (attributes.containsKey(jdbcAttribute)) + { + messageStoreSettings.put(jdbcAttribute, attributes.get(jdbcAttribute)); + } + } + } + } + + public class StandardVirtualHostUpgrader implements VirtualHostEntryUpgrader + { + Map<String, StoreEntryUpgrader> _messageStoreEntryUpgrader = new HashMap<String, StoreEntryUpgrader>() + {{ + put("JDBC", new JDBCMessageStoreEntryUpgrader()); + put("BDB", new GenericMessageStoreEntryUpgrader("BDB", new HashMap<String, String>() + {{ + put("storePath", "storePath"); + put("bdbEnvironmentConfig", "bdbEnvironmentConfig"); + put("storeUnderfullSize", "storeUnderfullSize"); + put("storeOverfullSize", "storeOverfullSize"); + }})); + put("DERBY", new GenericMessageStoreEntryUpgrader("DERBY", new HashMap<String, String>() + {{ + put("storePath", "storePath"); + put("storeUnderfullSize", "storeUnderfullSize"); + put("storeOverfullSize", "storeOverfullSize"); + }})); + put("MEMORY", new GenericMessageStoreEntryUpgrader("Memory", Collections.<String, String> emptyMap())); + }}; + Map<String, StoreEntryUpgrader> _configurationStoreEntryUpgrader = new HashMap<String, StoreEntryUpgrader>() + {{ + put("JDBC", new JDBCConfigurationStoreEntryUpgrader()); + put("DERBY", new GenericMessageStoreEntryUpgrader("DERBY", new HashMap<String, String>() + {{ + put("configStorePath", "storePath"); + put("configStoreType", "storeType"); + }})); + put("BDB", new GenericMessageStoreEntryUpgrader("BDB", new HashMap<String, String>() + {{ + put("configStoreType", "storeType"); + put("configStorePath", "storePath"); + put("bdbEnvironmentConfig", "bdbEnvironmentConfig"); + }})); + put("MEMORY", new GenericMessageStoreEntryUpgrader("Memory", + Collections.<String, String> singletonMap("configStoreType", "storeType"))); + put("JSON", new GenericMessageStoreEntryUpgrader("JSON", new HashMap<String, String>() + {{ + put("configStorePath", "storePath"); + put("configStoreType", "storeType"); + }})); + }}; + + @Override + public ConfigurationEntry upgrade(ConfigurationEntryStore store, ConfigurationEntry vhost) + { + Map<String, Object> attributes = vhost.getAttributes(); + Map<String, Object> newAttributes = new HashMap<String, Object>(attributes); + + String capitalisedStoreType = String.valueOf(attributes.get("storeType")).toUpperCase(); + StoreEntryUpgrader messageStoreSettingsUpgrader = _messageStoreEntryUpgrader.get(capitalisedStoreType); + Map<String, Object> messageStoreSettings = null; + if (messageStoreSettingsUpgrader != null) + { + messageStoreSettings = messageStoreSettingsUpgrader.upgrade(attributes); + } + + if (attributes.containsKey("configStoreType")) + { + String capitaliseConfigStoreType = ((String) attributes.get("configStoreType")).toUpperCase(); + StoreEntryUpgrader configurationStoreSettingsUpgrader = _configurationStoreEntryUpgrader + .get(capitaliseConfigStoreType); + Map<String, Object> configurationStoreSettings = configurationStoreSettingsUpgrader.upgrade(attributes); + newAttributes.keySet().removeAll(configurationStoreSettingsUpgrader.getNamesToBeDeleted()); + newAttributes.put("configurationStoreSettings", configurationStoreSettings); + } + + if (messageStoreSettingsUpgrader != null) + { + newAttributes.keySet().removeAll(messageStoreSettingsUpgrader.getNamesToBeDeleted()); + newAttributes.put("messageStoreSettings", messageStoreSettings); + } + + return new ConfigurationEntry(vhost.getId(), vhost.getType(), newAttributes, vhost.getChildrenIds(), store); + } + + } + +}
\ No newline at end of file diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/MemoryConfigurationEntryStore.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/MemoryConfigurationEntryStore.java index cc591b695e..7b03946680 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/MemoryConfigurationEntryStore.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/MemoryConfigurationEntryStore.java @@ -60,6 +60,7 @@ import org.codehaus.jackson.node.ArrayNode; public class MemoryConfigurationEntryStore implements ConfigurationEntryStore { + public static final String STORE_TYPE = "memory"; private static final String DEFAULT_BROKER_NAME = "Broker"; @@ -545,7 +546,11 @@ public class MemoryConfigurationEntryStore implements ConfigurationEntryStore } else if (fieldNode.isObject()) { - // ignore, in-line objects are not supported yet + if (attributes == null) + { + attributes = new HashMap<String, Object>(); + } + attributes.put(fieldName, toObject(fieldNode) ); } else { diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Model.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Model.java index f940b323be..c48c7bb7f6 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Model.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Model.java @@ -34,10 +34,11 @@ public class Model * * 1.0 Initial version * 1.1 Addition of mandatory virtual host type / different types of virtual host - * + * 1.3 Truststore/Keystore type => trustStoreType / type => keyStoreType + * 1.4 Separate messageStoreSettings from virtualhost */ public static final int MODEL_MAJOR_VERSION = 1; - public static final int MODEL_MINOR_VERSION = 3; + public static final int MODEL_MINOR_VERSION = 4; public static final String MODEL_VERSION = MODEL_MAJOR_VERSION + "." + MODEL_MINOR_VERSION; private static final Model MODEL_INSTANCE = new Model(); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java index d63a765144..928ea26819 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java @@ -22,8 +22,6 @@ package org.apache.qpid.server.model; import java.util.Collection; -import org.apache.qpid.server.message.MessageInstance; -import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.queue.QueueEntryVisitor; @ManagedObject diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java index 4aec9b38a0..f4072277d5 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java @@ -20,15 +20,15 @@ */ package org.apache.qpid.server.model; +import java.security.AccessControlException; +import java.util.Collection; +import java.util.Map; + import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.message.MessageInstance; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.store.MessageStore; -import java.security.AccessControlException; -import java.util.Collection; -import java.util.Map; - @ManagedObject( managesChildren = true ) public interface VirtualHost<X extends VirtualHost<X>> extends ConfiguredObject<X> { @@ -48,17 +48,14 @@ public interface VirtualHost<X extends VirtualHost<X>> extends ConfiguredObject< String STORE_TRANSACTION_IDLE_TIMEOUT_WARN = "storeTransactionIdleTimeoutWarn"; String STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE = "storeTransactionOpenTimeoutClose"; String STORE_TRANSACTION_OPEN_TIMEOUT_WARN = "storeTransactionOpenTimeoutWarn"; - String STORE_TYPE = "storeType"; - String STORE_PATH = "storePath"; - String CONFIG_STORE_TYPE = "configStoreType"; - String CONFIG_STORE_PATH = "configStorePath"; String SUPPORTED_EXCHANGE_TYPES = "supportedExchangeTypes"; String SUPPORTED_QUEUE_TYPES = "supportedQueueTypes"; String DURABLE = "durable"; String LIFETIME_POLICY = "lifetimePolicy"; - String CONFIG_PATH = "configPath"; - - // Attributes + String SECURITY_ACL = "securityAcl"; + String HOUSE_KEEPING_THREAD_COUNT = "houseKeepingThreadCount"; + String CONFIGURATION_STORE_SETTINGS = "configurationStoreSettings"; + String MESSAGE_STORE_SETTINGS = "messageStoreSettings"; int CURRENT_CONFIG_VERSION = 4; @@ -84,18 +81,6 @@ public interface VirtualHost<X extends VirtualHost<X>> extends ConfiguredObject< long getQueue_flowResumeSizeBytes(); @ManagedAttribute - String getConfigStoreType(); - - @ManagedAttribute - String getConfigStorePath(); - - @ManagedAttribute - String getStoreType(); - - @ManagedAttribute - String getStorePath(); - - @ManagedAttribute long getStoreTransactionIdleTimeoutClose(); @ManagedAttribute @@ -123,7 +108,16 @@ public interface VirtualHost<X extends VirtualHost<X>> extends ConfiguredObject< long getQueue_alertThresholdQueueDepthMessages(); @ManagedAttribute - String getConfigPath(); + String getSecurityAcl(); + + @ManagedAttribute + int getHouseKeepingThreadCount(); + + @ManagedAttribute + Map<String, Object> getMessageStoreSettings(); + + @ManagedAttribute + Map<String, Object> getConfigurationStoreSettings(); @ManagedStatistic long getQueueCount(); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/AbstractConfiguredObject.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/AbstractConfiguredObject.java index ec48aa7936..d263bb45b2 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/AbstractConfiguredObject.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/AbstractConfiguredObject.java @@ -408,6 +408,25 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im } } + <T extends ConfiguredObject<?>> Object getAttribute(String name, T parent, String parentAttributeName) + { + Object value = getActualAttribute(name); + if (value != null ) + { + return value; + } + if (parent != null) + { + value = parent.getAttribute(parentAttributeName); + if (value != null) + { + return value; + } + } + return getDefaultAttribute(name); + } + + @Override public String getDescription() { diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java index 02e37d6733..7fcdcfe61c 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java @@ -43,6 +43,7 @@ import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.logging.LogRecorder; import org.apache.qpid.server.logging.messages.BrokerMessages; import org.apache.qpid.server.model.*; +import org.apache.qpid.server.plugin.MessageStoreFactory; import org.apache.qpid.server.plugin.PreferencesProviderFactory; import org.apache.qpid.server.plugin.VirtualHostFactory; import org.apache.qpid.server.security.SecurityManager; @@ -50,7 +51,6 @@ import org.apache.qpid.server.security.SubjectCreator; import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.security.auth.manager.SimpleAuthenticationManager; import org.apache.qpid.server.stats.StatisticsGatherer; -import org.apache.qpid.server.store.MessageStoreCreator; import org.apache.qpid.server.util.MapValueConverter; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; import org.apache.qpid.util.SystemUtils; @@ -197,7 +197,7 @@ public class BrokerAdapter<X extends Broker<X>> extends AbstractConfiguredObject _portFactory = portFactory; _brokerOptions = brokerOptions; _securityManager = new SecurityManager(this, _brokerOptions.isManagementMode()); - _supportedVirtualHostStoreTypes = new MessageStoreCreator().getStoreTypes(); + _supportedVirtualHostStoreTypes = MessageStoreFactory.FACTORY_LOADER.getSupportedTypes(); _supportedBrokerStoreTypes = new BrokerConfigurationStoreCreator().getStoreTypes(); _brokerStore = brokerStore; if (_brokerOptions.isManagementMode()) @@ -262,7 +262,7 @@ public class BrokerAdapter<X extends Broker<X>> extends AbstractConfiguredObject @Override public Collection<String> getSupportedPreferencesProviderTypes() { - return PreferencesProviderFactory.FACTORIES.getDescriptiveTypes(); + return PreferencesProviderFactory.FACTORY_LOADER.getSupportedTypes(); } @Override @@ -969,7 +969,7 @@ public class BrokerAdapter<X extends Broker<X>> extends AbstractConfiguredObject } else if (SUPPORTED_PREFERENCES_PROVIDER_TYPES.equals(name)) { - return PreferencesProviderFactory.FACTORIES.getDescriptiveTypes(); + return PreferencesProviderFactory.FACTORY_LOADER.getSupportedTypes(); } else if (MODEL_VERSION.equals(name)) { diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java index 72b316c784..2e86d834bb 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java @@ -20,7 +20,6 @@ */ package org.apache.qpid.server.model.adapter; -import java.io.File; import java.lang.reflect.Type; import java.security.AccessControlException; import java.util.ArrayList; @@ -31,15 +30,9 @@ import java.util.List; import java.util.Map; import java.util.UUID; -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.PropertiesConfiguration; -import org.apache.commons.configuration.SystemConfiguration; import org.apache.log4j.Logger; import org.apache.qpid.server.exchange.AMQUnknownExchangeType; import org.apache.qpid.server.configuration.IllegalConfigurationException; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; -import org.apache.qpid.server.configuration.XmlConfigurationUtilities.MyConfiguration; import org.apache.qpid.server.exchange.ExchangeImpl; import org.apache.qpid.server.message.MessageInstance; import org.apache.qpid.server.message.ServerMessage; @@ -56,6 +49,7 @@ import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.txn.LocalTransaction; import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.server.util.MapValueConverter; +import org.apache.qpid.server.util.ParameterizedTypeImpl; import org.apache.qpid.server.plugin.VirtualHostFactory; import org.apache.qpid.server.util.ServerScopedRuntimeException; import org.apache.qpid.server.virtualhost.ExchangeExistsException; @@ -73,10 +67,32 @@ public final class VirtualHostAdapter extends AbstractConfiguredObject<VirtualHo public static final Map<String, Type> ATTRIBUTE_TYPES = Collections.unmodifiableMap(new HashMap<String, Type>(){{ put(NAME, String.class); put(TYPE, String.class); - put(STORE_PATH, String.class); - put(STORE_TYPE, String.class); - put(CONFIG_PATH, String.class); put(STATE, State.class); + + put(QUEUE_ALERT_REPEAT_GAP, Long.class); + put(QUEUE_ALERT_THRESHOLD_MESSAGE_AGE, Long.class); + put(QUEUE_ALERT_THRESHOLD_MESSAGE_SIZE, Long.class); + put(QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_BYTES, Long.class); + put(QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, Long.class); + put(QUEUE_DEAD_LETTER_QUEUE_ENABLED, Boolean.class); + put(QUEUE_MAXIMUM_DELIVERY_ATTEMPTS, Integer.class); + put(QUEUE_FLOW_CONTROL_SIZE_BYTES, Long.class); + put(QUEUE_FLOW_RESUME_SIZE_BYTES, Long.class); + + put(HOUSEKEEPING_CHECK_PERIOD, Long.class); + put(STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE, Long.class); + put(STORE_TRANSACTION_IDLE_TIMEOUT_WARN, Long.class); + put(STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE, Long.class); + put(STORE_TRANSACTION_OPEN_TIMEOUT_WARN, Long.class); + + put(MESSAGE_STORE_SETTINGS, new ParameterizedTypeImpl(Map.class, String.class, Object.class)); + put(CONFIGURATION_STORE_SETTINGS, new ParameterizedTypeImpl(Map.class, String.class, Object.class)); + + }}); + + @SuppressWarnings("serial") + private static final Map<String, Object> DEFAULTS = Collections.unmodifiableMap(new HashMap<String, Object>(){{ + put(HOUSE_KEEPING_THREAD_COUNT, Runtime.getRuntime().availableProcessors()); }}); private org.apache.qpid.server.virtualhost.VirtualHost _virtualHost; @@ -90,7 +106,7 @@ public final class VirtualHostAdapter extends AbstractConfiguredObject<VirtualHo public VirtualHostAdapter(UUID id, Map<String, Object> attributes, Broker<?> broker, StatisticsGatherer brokerStatisticsGatherer, TaskExecutor taskExecutor) { - super(id, Collections.<String,Object>emptyMap(), MapValueConverter.convert(attributes, ATTRIBUTE_TYPES, false), taskExecutor, false); + super(id, DEFAULTS, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES, false), taskExecutor, false); _broker = broker; _brokerStatisticsGatherer = brokerStatisticsGatherer; validateAttributes(); @@ -104,58 +120,19 @@ public final class VirtualHostAdapter extends AbstractConfiguredObject<VirtualHo { throw new IllegalConfigurationException("Virtual host name must be specified"); } - - String configurationFile = (String) getAttribute(CONFIG_PATH); - String type = (String) getAttribute(TYPE); - - boolean invalidAttributes = false; - if (configurationFile == null) - { - if (type == null) - { - invalidAttributes = true; - } - else - { - validateAttributes(type); - } - }/* - else + String type = getType(); + if (type == null || "".equals(type.trim())) { - if (type != null) - { - invalidAttributes = true; - } - - }*/ - if (invalidAttributes) - { - throw new IllegalConfigurationException("Please specify either the 'configPath' attribute or 'type' attributes"); - } - - // pre-load the configuration in order to validate - try - { - createVirtualHostConfiguration(name); - } - catch(ConfigurationException e) - { - throw new IllegalConfigurationException("Failed to validate configuration", e); + throw new IllegalConfigurationException("Virtual host type must be specified"); } - } - - private void validateAttributes(String type) - { final VirtualHostFactory factory = VirtualHostFactory.FACTORIES.get(type); if(factory == null) { throw new IllegalArgumentException("Unknown virtual host type '"+ type +"'. Valid types are: " + VirtualHostFactory.TYPES.get()); } factory.validateAttributes(getActualAttributes()); - } - public Collection<VirtualHostAlias> getAliases() { return Collections.unmodifiableCollection(_aliases); @@ -682,95 +659,88 @@ public final class VirtualHostAdapter extends AbstractConfiguredObject<VirtualHo { return LifetimePolicy.PERMANENT; } - else if (_virtualHost != null) + else if(QUEUE_ALERT_REPEAT_GAP.equals(name)) { - return getAttributeFromVirtualHostImplementation(name); + return getAttribute(QUEUE_ALERT_REPEAT_GAP, Broker.QUEUE_ALERT_REPEAT_GAP); } - return super.getAttribute(name); - } - - private Object getAttributeFromVirtualHostImplementation(String name) - { - if(SUPPORTED_EXCHANGE_TYPES.equals(name)) + else if(QUEUE_ALERT_THRESHOLD_MESSAGE_AGE.equals(name)) { - List<String> types = new ArrayList<String>(); - for(@SuppressWarnings("rawtypes") ExchangeType type : _virtualHost.getExchangeTypes()) - { - types.add(type.getType()); - } - return Collections.unmodifiableCollection(types); + return getAttribute(QUEUE_ALERT_THRESHOLD_MESSAGE_AGE, Broker.QUEUE_ALERT_THRESHOLD_MESSAGE_AGE); } - else if(SUPPORTED_QUEUE_TYPES.equals(name)) + else if(QUEUE_ALERT_THRESHOLD_MESSAGE_SIZE.equals(name)) { - // TODO + return getAttribute(QUEUE_ALERT_THRESHOLD_MESSAGE_SIZE, Broker.QUEUE_ALERT_THRESHOLD_MESSAGE_SIZE); } - else if(QUEUE_DEAD_LETTER_QUEUE_ENABLED.equals(name)) + else if(QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_BYTES.equals(name)) { - return _virtualHost.getConfiguration().isDeadLetterQueueEnabled(); + return getAttribute(QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_BYTES, Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_BYTES); } - else if(HOUSEKEEPING_CHECK_PERIOD.equals(name)) + else if(QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES.equals(name)) + { + return getAttribute(QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES); + } + else if(QUEUE_DEAD_LETTER_QUEUE_ENABLED.equals(name)) { - return _virtualHost.getConfiguration().getHousekeepingCheckPeriod(); + return getAttribute(QUEUE_DEAD_LETTER_QUEUE_ENABLED, Broker.QUEUE_DEAD_LETTER_QUEUE_ENABLED); } else if(QUEUE_MAXIMUM_DELIVERY_ATTEMPTS.equals(name)) { - return _virtualHost.getConfiguration().getMaxDeliveryCount(); + return getAttribute(QUEUE_MAXIMUM_DELIVERY_ATTEMPTS, Broker.QUEUE_MAXIMUM_DELIVERY_ATTEMPTS); } else if(QUEUE_FLOW_CONTROL_SIZE_BYTES.equals(name)) { - return _virtualHost.getConfiguration().getCapacity(); + return getAttribute(QUEUE_FLOW_CONTROL_SIZE_BYTES, Broker.QUEUE_FLOW_CONTROL_SIZE_BYTES); } else if(QUEUE_FLOW_RESUME_SIZE_BYTES.equals(name)) { - return _virtualHost.getConfiguration().getFlowResumeCapacity(); + return getAttribute(QUEUE_FLOW_RESUME_SIZE_BYTES, Broker.QUEUE_FLOW_CONTROL_RESUME_SIZE_BYTES); } - else if(STORE_TYPE.equals(name)) - { - return _virtualHost.getMessageStore().getStoreType(); - } - else if(STORE_PATH.equals(name)) + else if(HOUSEKEEPING_CHECK_PERIOD.equals(name)) { - return _virtualHost.getMessageStore().getStoreLocation(); + return getAttribute(HOUSEKEEPING_CHECK_PERIOD, Broker.VIRTUALHOST_HOUSEKEEPING_CHECK_PERIOD); } else if(STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE.equals(name)) { - return _virtualHost.getConfiguration().getTransactionTimeoutIdleClose(); + return getAttribute(STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE, Broker.VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE); } else if(STORE_TRANSACTION_IDLE_TIMEOUT_WARN.equals(name)) { - return _virtualHost.getConfiguration().getTransactionTimeoutIdleWarn(); + return getAttribute(STORE_TRANSACTION_IDLE_TIMEOUT_WARN, Broker.VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_WARN); } else if(STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE.equals(name)) { - return _virtualHost.getConfiguration().getTransactionTimeoutOpenClose(); + return getAttribute(STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE, Broker.VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE); } else if(STORE_TRANSACTION_OPEN_TIMEOUT_WARN.equals(name)) { - return _virtualHost.getConfiguration().getTransactionTimeoutOpenWarn(); - } - else if(QUEUE_ALERT_REPEAT_GAP.equals(name)) - { - return _virtualHost.getConfiguration().getMinimumAlertRepeatGap(); - } - else if(QUEUE_ALERT_THRESHOLD_MESSAGE_AGE.equals(name)) - { - return _virtualHost.getConfiguration().getMaximumMessageAge(); - } - else if(QUEUE_ALERT_THRESHOLD_MESSAGE_SIZE.equals(name)) - { - return _virtualHost.getConfiguration().getMaximumMessageSize(); - } - else if(QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_BYTES.equals(name)) - { - return _virtualHost.getConfiguration().getMaximumQueueDepth(); + return getAttribute(STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE, Broker.VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_WARN); } - else if(QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES.equals(name)) + else if (_virtualHost != null) { - return _virtualHost.getConfiguration().getMaximumMessageCount(); + if(SUPPORTED_EXCHANGE_TYPES.equals(name)) + { + List<String> types = new ArrayList<String>(); + for(@SuppressWarnings("rawtypes") ExchangeType type : _virtualHost.getExchangeTypes()) + { + types.add(type.getType()); + } + return Collections.unmodifiableCollection(types); + } + else if(SUPPORTED_QUEUE_TYPES.equals(name)) + { + // TODO + } } return super.getAttribute(name); } + + Object getAttribute(String name, String brokerAttributeName) + { + return getAttribute(name, _broker, brokerAttributeName); + } + + @Override public Collection<String> getAttributeNames() { @@ -807,115 +777,99 @@ public final class VirtualHostAdapter extends AbstractConfiguredObject<VirtualHo @Override public boolean isQueue_deadLetterQueueEnabled() { - return _virtualHost.getConfiguration().isDeadLetterQueueEnabled(); + return (Boolean)getAttribute(VirtualHost.QUEUE_DEAD_LETTER_QUEUE_ENABLED); } @Override public long getHousekeepingCheckPeriod() { - return _virtualHost.getConfiguration().getHousekeepingCheckPeriod(); + return (Long)getAttribute(VirtualHost.HOUSEKEEPING_CHECK_PERIOD); } @Override public int getQueue_maximumDeliveryAttempts() { - return _virtualHost.getConfiguration().getMaxDeliveryCount(); + return (Integer)getAttribute(VirtualHost.QUEUE_MAXIMUM_DELIVERY_ATTEMPTS); } @Override public long getQueue_flowControlSizeBytes() { - return _virtualHost.getConfiguration().getCapacity(); + return (Long)getAttribute(VirtualHost.QUEUE_FLOW_CONTROL_SIZE_BYTES); } @Override public long getQueue_flowResumeSizeBytes() { - return _virtualHost.getConfiguration().getFlowResumeCapacity(); - } - - @Override - public String getConfigStoreType() - { - return (String) getAttribute(CONFIG_STORE_TYPE); - } - - @Override - public String getConfigStorePath() - { - return (String) getAttribute(CONFIG_PATH); - } - - @Override - public String getStoreType() - { - return _virtualHost.getMessageStore().getStoreType(); - } - - @Override - public String getStorePath() - { - return _virtualHost.getMessageStore().getStoreLocation(); + return (Long)getAttribute(VirtualHost.QUEUE_FLOW_RESUME_SIZE_BYTES); } @Override public long getStoreTransactionIdleTimeoutClose() { - return _virtualHost.getConfiguration().getTransactionTimeoutIdleClose(); + return (Long)getAttribute(VirtualHost.STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE); } @Override public long getStoreTransactionIdleTimeoutWarn() { - return _virtualHost.getConfiguration().getTransactionTimeoutIdleWarn(); + return (Long)getAttribute(VirtualHost.STORE_TRANSACTION_IDLE_TIMEOUT_WARN); } @Override public long getStoreTransactionOpenTimeoutClose() { - return _virtualHost.getConfiguration().getTransactionTimeoutOpenClose(); + return (Long)getAttribute(VirtualHost.STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE); } @Override public long getStoreTransactionOpenTimeoutWarn() { - return _virtualHost.getConfiguration().getTransactionTimeoutOpenWarn(); + return (Long)getAttribute(VirtualHost.STORE_TRANSACTION_OPEN_TIMEOUT_WARN); } @Override public long getQueue_alertRepeatGap() { - return _virtualHost.getConfiguration().getMinimumAlertRepeatGap(); + return (Long)getAttribute(VirtualHost.QUEUE_ALERT_REPEAT_GAP); } @Override public long getQueue_alertThresholdMessageAge() { - return _virtualHost.getConfiguration().getMaximumMessageAge(); + return (Long)getAttribute(VirtualHost.QUEUE_ALERT_THRESHOLD_MESSAGE_AGE); } @Override public long getQueue_alertThresholdMessageSize() { - return _virtualHost.getConfiguration().getMaximumMessageSize(); + return (Long)getAttribute(VirtualHost.QUEUE_ALERT_THRESHOLD_MESSAGE_SIZE); } @Override public long getQueue_alertThresholdQueueDepthBytes() { - return _virtualHost.getConfiguration().getMaximumQueueDepth(); + return (Long)getAttribute(VirtualHost.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_BYTES); } @Override public long getQueue_alertThresholdQueueDepthMessages() { - return _virtualHost.getConfiguration().getMaximumMessageCount(); + return (Long)getAttribute(VirtualHost.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES); } + @SuppressWarnings("unchecked") @Override - public String getConfigPath() + public Map<String, Object> getMessageStoreSettings() { - return (String) getAttribute(CONFIG_PATH); + return (Map<String, Object>)getAttribute(VirtualHost.MESSAGE_STORE_SETTINGS); + } + + @SuppressWarnings("unchecked") + @Override + public Map<String, Object> getConfigurationStoreSettings() + { + return (Map<String, Object>)getAttribute(VirtualHost.CONFIGURATION_STORE_SETTINGS); } @Override @@ -960,6 +914,17 @@ public final class VirtualHostAdapter extends AbstractConfiguredObject<VirtualHo return _virtualHost.getMessageDeliveryStatistics().getTotal(); } + @Override + public String getSecurityAcl() + { + return (String)getAttribute(SECURITY_ACL); + } + + @Override + public int getHouseKeepingThreadCount() + { + return (Integer)getAttribute(HOUSE_KEEPING_THREAD_COUNT); + } @Override protected boolean setState(State currentState, State desiredState) @@ -1041,8 +1006,7 @@ public final class VirtualHostAdapter extends AbstractConfiguredObject<VirtualHo String virtualHostName = getName(); try { - VirtualHostConfiguration configuration = createVirtualHostConfiguration(virtualHostName); - String type = configuration.getType(); + String type = (String) getAttribute(TYPE); final VirtualHostFactory factory = VirtualHostFactory.FACTORIES.get(type); if(factory == null) { @@ -1053,11 +1017,10 @@ public final class VirtualHostAdapter extends AbstractConfiguredObject<VirtualHo _virtualHost = factory.createVirtualHost(_broker.getVirtualHostRegistry(), _brokerStatisticsGatherer, _broker.getSecurityManager(), - configuration, this); } } - catch (ConfigurationException e) + catch (Exception e) { throw new ServerScopedRuntimeException("Failed to create virtual host " + virtualHostName, e); } @@ -1078,53 +1041,6 @@ public final class VirtualHostAdapter extends AbstractConfiguredObject<VirtualHo } } - private VirtualHostConfiguration createVirtualHostConfiguration(String virtualHostName) throws ConfigurationException - { - VirtualHostConfiguration configuration; - String configurationFile = (String)getAttribute(CONFIG_PATH); - if (configurationFile == null) - { - final MyConfiguration basicConfiguration = new MyConfiguration(); - PropertiesConfiguration config = new PropertiesConfiguration(); - final String type = (String) getAttribute(TYPE); - config.addProperty("type", type); - VirtualHostFactory factory = VirtualHostFactory.FACTORIES.get(type); - if(factory != null) - { - for(Map.Entry<String,Object> entry : factory.createVirtualHostConfiguration(this).entrySet()) - { - config.addProperty(entry.getKey(), entry.getValue()); - } - } - basicConfiguration.addConfiguration(config); - - CompositeConfiguration compositeConfiguration = new CompositeConfiguration(); - compositeConfiguration.addConfiguration(new SystemConfiguration()); - compositeConfiguration.addConfiguration(basicConfiguration); - configuration = new VirtualHostConfiguration(virtualHostName, compositeConfiguration , _broker); - } - else - { - if (!new File(configurationFile).exists()) - { - throw new IllegalConfigurationException("Configuration file '" + configurationFile + "' does not exist"); - } - configuration = new VirtualHostConfiguration(virtualHostName, new File(configurationFile) , _broker); - String type = configuration.getType(); - changeAttribute(TYPE,null,type); - VirtualHostFactory factory = VirtualHostFactory.FACTORIES.get(type); - if(factory != null) - { - for(Map.Entry<String,Object> entry : factory.convertVirtualHostConfiguration(configuration.getConfig()).entrySet()) - { - changeAttribute(entry.getKey(), getAttribute(entry.getKey()), entry.getValue()); - } - } - - } - return configuration; - } - @Override public SecurityManager getSecurityManager() { @@ -1177,4 +1093,5 @@ public final class VirtualHostAdapter extends AbstractConfiguredObject<VirtualHo { return super.getTaskExecutor(); } + } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/DurableConfigurationStoreFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/DurableConfigurationStoreFactory.java index 94a029ced3..b83222f798 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/DurableConfigurationStoreFactory.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/DurableConfigurationStoreFactory.java @@ -21,9 +21,7 @@ package org.apache.qpid.server.plugin; import java.util.Map; -import org.apache.commons.configuration.Configuration; import org.apache.qpid.server.store.DurableConfigurationStore; -import org.apache.qpid.server.store.MessageStore; public interface DurableConfigurationStoreFactory extends Pluggable { diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/JDBCConnectionProviderFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/JDBCConnectionProviderFactory.java index 12fb9224bb..c6b350d65b 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/JDBCConnectionProviderFactory.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/JDBCConnectionProviderFactory.java @@ -25,15 +25,15 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; -import org.apache.commons.configuration.Configuration; -import org.apache.qpid.server.model.VirtualHost; +import java.util.Map; + import org.apache.qpid.server.store.jdbc.ConnectionProvider; public interface JDBCConnectionProviderFactory extends Pluggable { String getType(); - ConnectionProvider getConnectionProvider(String connectionUrl, VirtualHost virtualHost) + ConnectionProvider getConnectionProvider(String connectionUrl, Map<String, Object> storeSettings) throws SQLException; static final class TYPES diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/MessageStoreFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/MessageStoreFactory.java index 81404dcba8..bae6738f23 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/MessageStoreFactory.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/MessageStoreFactory.java @@ -21,16 +21,16 @@ package org.apache.qpid.server.plugin; import java.util.Map; -import org.apache.commons.configuration.Configuration; + import org.apache.qpid.server.store.MessageStore; public interface MessageStoreFactory extends Pluggable { + PluggableFactoryLoader<MessageStoreFactory> FACTORY_LOADER = new PluggableFactoryLoader<MessageStoreFactory>(MessageStoreFactory.class); + String getType(); MessageStore createMessageStore(); - public Map<String, Object> convertStoreConfiguration(Configuration configuration); - void validateAttributes(Map<String, Object> attributes); } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/PluggableFactoryLoader.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/PluggableFactoryLoader.java index 7a8b7c0c65..40db520ff1 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/PluggableFactoryLoader.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/PluggableFactoryLoader.java @@ -19,7 +19,6 @@ package org.apache.qpid.server.plugin; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -56,7 +55,7 @@ public class PluggableFactoryLoader<T extends Pluggable> return _factoriesMap.get(type); } - public Collection<String> getDescriptiveTypes() + public Set<String> getSupportedTypes() { return _types; } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/PreferencesProviderFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/PreferencesProviderFactory.java index 05de1950f7..9665dfffbb 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/PreferencesProviderFactory.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/PreferencesProviderFactory.java @@ -26,7 +26,7 @@ import org.apache.qpid.server.model.PreferencesProvider; public interface PreferencesProviderFactory extends Pluggable { - PluggableFactoryLoader<PreferencesProviderFactory> FACTORIES = new PluggableFactoryLoader<PreferencesProviderFactory>(PreferencesProviderFactory.class); + PluggableFactoryLoader<PreferencesProviderFactory> FACTORY_LOADER = new PluggableFactoryLoader<PreferencesProviderFactory>(PreferencesProviderFactory.class); PreferencesProvider createInstance(UUID id, Map<String, Object> attributes, AuthenticationProvider<? extends AuthenticationProvider> authenticationProvider); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/VirtualHostFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/VirtualHostFactory.java index a073c89a1b..80ad347929 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/VirtualHostFactory.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/VirtualHostFactory.java @@ -25,9 +25,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; -import org.apache.commons.configuration.Configuration; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; -import org.apache.qpid.server.model.adapter.VirtualHostAdapter; + import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.stats.StatisticsGatherer; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -40,15 +38,10 @@ public interface VirtualHostFactory extends Pluggable VirtualHost createVirtualHost(VirtualHostRegistry virtualHostRegistry, StatisticsGatherer brokerStatisticsGatherer, SecurityManager parentSecurityManager, - VirtualHostConfiguration hostConfig, org.apache.qpid.server.model.VirtualHost virtualHost); void validateAttributes(Map<String, Object> attributes); - Map<String, Object> createVirtualHostConfiguration(VirtualHostAdapter virtualHostAdapter); - - Map<String,Object> convertVirtualHostConfiguration(Configuration configuration); - static final class TYPES { private TYPES() diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java index dd82dfd681..3098572e39 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java @@ -26,11 +26,9 @@ import java.util.UUID; import org.apache.qpid.server.exchange.AMQUnknownExchangeType; import org.apache.qpid.server.exchange.ExchangeImpl; -import org.apache.qpid.server.model.ExclusivityPolicy; import org.apache.qpid.server.model.LifetimePolicy; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.server.configuration.BrokerProperties; -import org.apache.qpid.server.configuration.QueueConfiguration; import org.apache.qpid.server.exchange.DefaultExchangeFactory; import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.model.UUIDGenerator; @@ -74,50 +72,10 @@ public class AMQQueueFactory implements QueueFactory return createOrRestoreQueue(attributes, true); } - private AMQQueue createOrRestoreQueue(Map<String, Object> attributes, - boolean createInStore) + private AMQQueue createOrRestoreQueue(Map<String, Object> attributes, boolean createInStore) { - - String queueName = MapValueConverter.getStringAttribute(Queue.NAME,attributes); - - QueueConfiguration config = _virtualHost.getConfiguration().getQueueConfiguration(queueName); - - if (!attributes.containsKey(Queue.ALERT_THRESHOLD_MESSAGE_AGE) && config.getMaximumMessageAge() != 0) - { - attributes.put(Queue.ALERT_THRESHOLD_MESSAGE_AGE, config.getMaximumMessageAge()); - } - if (!attributes.containsKey(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_BYTES) && config.getMaximumQueueDepth() != 0) - { - attributes.put(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_BYTES, config.getMaximumQueueDepth()); - } - if (!attributes.containsKey(Queue.ALERT_THRESHOLD_MESSAGE_SIZE) && config.getMaximumMessageSize() != 0) - { - attributes.put(Queue.ALERT_THRESHOLD_MESSAGE_SIZE, config.getMaximumMessageSize()); - } - if (!attributes.containsKey(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES) && config.getMaximumMessageCount() != 0) - { - attributes.put(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, config.getMaximumMessageCount()); - } - if (!attributes.containsKey(Queue.ALERT_REPEAT_GAP) && config.getMinimumAlertRepeatGap() != 0) - { - attributes.put(Queue.ALERT_REPEAT_GAP, config.getMinimumAlertRepeatGap()); - } - if (config.getMaxDeliveryCount() != 0 && !attributes.containsKey(Queue.MAXIMUM_DELIVERY_ATTEMPTS)) - { - attributes.put(Queue.MAXIMUM_DELIVERY_ATTEMPTS, config.getMaxDeliveryCount()); - } - if (!attributes.containsKey(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES) && config.getCapacity() != 0) - { - attributes.put(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, config.getCapacity()); - } - if (!attributes.containsKey(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES) && config.getFlowResumeCapacity() != 0) - { - attributes.put(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, config.getFlowResumeCapacity()); - } - - - boolean createDLQ = createDLQ(attributes, config); + boolean createDLQ = shouldCreateDLQ(attributes, _virtualHost.getDefaultDeadLetterQueueEnabled()); if (createDLQ) { validateDLNames(queueName); @@ -259,30 +217,7 @@ public class AMQQueueFactory implements QueueFactory queue.setAlternateExchange(dlExchange); } - public AMQQueue createAMQQueueImpl(QueueConfiguration config) - { - - Map<String, Object> arguments = createQueueAttributesFromConfig(_virtualHost, config); - - AMQQueue q = createOrRestoreQueue(arguments, false); - return q; - } - - /** - * Validates DLQ and DLE names - * <p> - * DLQ name and DLQ exchange name need to be validated in order to keep - * integrity in cases when queue name passes validation check but DLQ name - * or DL exchange name fails to pass it. Otherwise, we might have situations - * when queue is created but DL exchange or/and DLQ creation fail. - * <p> - * - * @param name - * queue name - * @throws IllegalArgumentException - * thrown if length of queue name or exchange name exceed 255 - */ - protected static void validateDLNames(String name) + private static void validateDLNames(String name) { // check if DLQ name and DLQ exchange name do not exceed 255 String exchangeName = getDeadLetterExchangeName(name); @@ -299,16 +234,7 @@ public class AMQQueueFactory implements QueueFactory } } - /** - * Checks if DLQ is enabled for the queue. - * - * @param arguments - * queue arguments - * @param qConfig - * queue configuration - * @return true if DLQ enabled - */ - protected static boolean createDLQ(Map<String, Object> arguments, QueueConfiguration qConfig) + private static boolean shouldCreateDLQ(Map<String, Object> arguments, boolean virtualHostDefaultDeadLetterQueueEnabled) { boolean autoDelete = MapValueConverter.getEnumAttribute(LifetimePolicy.class, Queue.LIFETIME_POLICY, @@ -320,7 +246,7 @@ public class AMQQueueFactory implements QueueFactory { boolean dlqArgumentPresent = arguments != null && arguments.containsKey(Queue.CREATE_DLQ_ON_CREATION); - if (dlqArgumentPresent || qConfig.isDeadLetterQueueEnabled()) + if (dlqArgumentPresent) { boolean dlqEnabled = true; if (dlqArgumentPresent) @@ -329,89 +255,21 @@ public class AMQQueueFactory implements QueueFactory dlqEnabled = (argument instanceof Boolean && ((Boolean)argument).booleanValue()) || (argument instanceof String && Boolean.parseBoolean(argument.toString())); } - return dlqEnabled ; + return dlqEnabled; } + return virtualHostDefaultDeadLetterQueueEnabled; } return false; } - /** - * Generates a dead letter queue name for a given queue name - * - * @param name - * queue name - * @return DLQ name - */ - protected static String getDeadLetterQueueName(String name) + private static String getDeadLetterQueueName(String name) { return name + System.getProperty(BrokerProperties.PROPERTY_DEAD_LETTER_QUEUE_SUFFIX, DEFAULT_DLQ_NAME_SUFFIX); } - /** - * Generates a dead letter exchange name for a given queue name - * - * @param name - * queue name - * @return DL exchange name - */ - protected static String getDeadLetterExchangeName(String name) + private static String getDeadLetterExchangeName(String name) { return name + System.getProperty(BrokerProperties.PROPERTY_DEAD_LETTER_EXCHANGE_SUFFIX, DefaultExchangeFactory.DEFAULT_DLE_NAME_SUFFIX); } - private static Map<String, Object> createQueueAttributesFromConfig(final VirtualHost virtualHost, - QueueConfiguration config) - { - Map<String,Object> attributes = new HashMap<String,Object>(); - - if(config.getArguments() != null && !config.getArguments().isEmpty()) - { - attributes.putAll(QueueArgumentsConverter.convertWireArgsToModel(new HashMap<String, Object>(config.getArguments()))); - } - - if(config.isLVQ() || config.getLVQKey() != null) - { - attributes.put(Queue.LVQ_KEY, - config.getLVQKey() == null ? ConflationQueue.DEFAULT_LVQ_KEY : config.getLVQKey()); - } - else if (config.getPriority() || config.getPriorities() > 0) - { - attributes.put(Queue.PRIORITIES, config.getPriorities() < 0 ? 10 : config.getPriorities()); - } - else if (config.getQueueSortKey() != null && !"".equals(config.getQueueSortKey())) - { - attributes.put(Queue.SORT_KEY, config.getQueueSortKey()); - } - - if (!config.getAutoDelete() && config.isDeadLetterQueueEnabled()) - { - attributes.put(Queue.CREATE_DLQ_ON_CREATION, true); - } - - if (config.getDescription() != null && !"".equals(config.getDescription())) - { - attributes.put(Queue.DESCRIPTION, config.getDescription()); - } - - attributes.put(Queue.DURABLE, config.getDurable()); - attributes.put(Queue.LIFETIME_POLICY, - config.getAutoDelete() ? LifetimePolicy.DELETE_ON_NO_OUTBOUND_LINKS : LifetimePolicy.PERMANENT); - if(config.getExclusive()) - { - attributes.put(Queue.EXCLUSIVE, ExclusivityPolicy.CONTAINER); - } - if(config.getOwner() != null) - { - attributes.put(Queue.OWNER, config.getOwner()); - } - - attributes.put(Queue.NAME, config.getName()); - - // we need queues that are defined in config to have deterministic ids. - attributes.put(Queue.ID, UUIDGenerator.generateQueueUUID(config.getName(), virtualHost.getName())); - - - return attributes; - } - } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java index 7c521c1f8a..17c9a19e50 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java @@ -135,7 +135,7 @@ public abstract class AbstractAuthenticationManager<T extends AbstractAuthentica { String name = MapValueConverter.getStringAttribute(PreferencesProvider.NAME, attributes); String type = MapValueConverter.getStringAttribute(PreferencesProvider.TYPE, attributes); - PreferencesProviderFactory factory = PreferencesProviderFactory.FACTORIES.get(type); + PreferencesProviderFactory factory = PreferencesProviderFactory.FACTORY_LOADER.get(type); UUID id = UUIDGenerator.generatePreferencesProviderUUID(name, getName()); PreferencesProvider pp = factory.createInstance(id, attributes, this); pp.setDesiredState(State.INITIALISING, State.ACTIVE); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java index 589eca1600..5921abc324 100755 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java @@ -27,6 +27,8 @@ import org.apache.qpid.server.model.VirtualHost; public interface DurableConfigurationStore { + String STORE_TYPE = "storeType"; + String STORE_PATH = "storePath"; public static interface Source { diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java index 3de601d741..2f869201cf 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java @@ -87,9 +87,12 @@ public class JsonFileConfigStore implements DurableConfigurationStore } } - protected void setup(final VirtualHost virtualHost) + private void setup(final VirtualHost virtualHost) { - Object storePathAttr = virtualHost.getAttribute(VirtualHost.CONFIG_STORE_PATH); + @SuppressWarnings("unchecked") + Map<String, Object> configurationStoreSettings = virtualHost.getConfigurationStoreSettings(); + + Object storePathAttr = configurationStoreSettings.get(DurableConfigurationStore.STORE_PATH); if(!(storePathAttr instanceof String)) { throw new StoreException("Cannot determine path for configuration storage"); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStoreFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStoreFactory.java index 374a35d10d..83c8ec2a21 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStoreFactory.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStoreFactory.java @@ -21,6 +21,7 @@ package org.apache.qpid.server.store; import java.util.Map; + import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.plugin.DurableConfigurationStoreFactory; @@ -41,10 +42,13 @@ public class JsonFileConfigStoreFactory implements DurableConfigurationStoreFact @Override public void validateAttributes(Map<String, Object> attributes) { - Object storePath = attributes.get(VirtualHost.CONFIG_STORE_PATH); + @SuppressWarnings("unchecked") + Map<String, Object> configurationStoreSettings = (Map<String, Object>) attributes.get(VirtualHost.CONFIGURATION_STORE_SETTINGS); + + Object storePath = configurationStoreSettings.get(DurableConfigurationStore.STORE_PATH); if(!(storePath instanceof String)) { - throw new IllegalArgumentException("Attribute '"+ VirtualHost.CONFIG_STORE_PATH + throw new IllegalArgumentException("Setting '"+ DurableConfigurationStore.STORE_PATH +"' is required and must be of type String."); } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/MessageStore.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/MessageStore.java index 626b999d72..b3a6216c84 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/MessageStore.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/MessageStore.java @@ -28,6 +28,11 @@ import org.apache.qpid.server.model.VirtualHost; */ public interface MessageStore { + String STORE_TYPE = "storeType"; + String STORE_PATH = "storePath"; + String UNDERFULL_SIZE = "storeUnderfullSize"; + String OVERFULL_SIZE = "storeOverfullSize"; + /** * Called after instantiation in order to configure the message store. A particular implementation can define * whatever parameters it wants. diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/MessageStoreCreator.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/MessageStoreCreator.java deleted file mode 100644 index a8013b8e9b..0000000000 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/MessageStoreCreator.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * - * 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; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.apache.qpid.server.configuration.IllegalConfigurationException; -import org.apache.qpid.server.plugin.MessageStoreFactory; -import org.apache.qpid.server.plugin.QpidServiceLoader; - -public class MessageStoreCreator -{ - private Map<String, MessageStoreFactory> _factories = new HashMap<String, MessageStoreFactory>(); - - public MessageStoreCreator() - { - QpidServiceLoader<MessageStoreFactory> qpidServiceLoader = new QpidServiceLoader<MessageStoreFactory>(); - Iterable<MessageStoreFactory> factories = qpidServiceLoader.atLeastOneInstanceOf(MessageStoreFactory.class); - for (MessageStoreFactory messageStoreFactory : factories) - { - String type = messageStoreFactory.getType(); - MessageStoreFactory factory = _factories.put(type.toLowerCase(), messageStoreFactory); - if (factory != null) - { - throw new IllegalStateException("MessageStoreFactory with type name '" + type - + "' is already registered using class '" + factory.getClass().getName() + "', can not register class '" - + messageStoreFactory.getClass().getName() + "'"); - } - } - } - - public boolean isValidType(String storeType) - { - return _factories.containsKey(storeType.toLowerCase()); - } - - - public MessageStore createMessageStore(String storeType) - { - MessageStoreFactory factory = _factories.get(storeType.toLowerCase()); - if (factory == null) - { - throw new IllegalConfigurationException("Unknown store type: " + storeType - + ". Supported types: " + _factories.keySet()); - } - return factory.createMessageStore(); - } - - public Collection<MessageStoreFactory> getFactories() - { - return Collections.unmodifiableCollection(_factories.values()); - } - - public Collection<String> getStoreTypes() - { - return Collections.unmodifiableCollection(_factories.keySet()); - } -} diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/StateManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/StateManager.java index e4efc26477..63612da455 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/StateManager.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/StateManager.java @@ -24,8 +24,6 @@ package org.apache.qpid.server.store; import java.util.EnumMap; import java.util.Map; -import org.apache.qpid.server.store.StateManager.Transition; - public class StateManager { private State _state = State.INITIAL; @@ -78,7 +76,8 @@ public class StateManager public static final Transition ACTIVATE = new Transition(State.INITIALISED, State.ACTIVATING, Event.BEFORE_ACTIVATE); public static final Transition ACTIVATE_COMPLETE = new Transition(State.ACTIVATING, State.ACTIVE, Event.AFTER_ACTIVATE); - public static final Transition CLOSE_INITIALISED = new Transition(State.INITIALISED, State.CLOSING, Event.BEFORE_CLOSE);; + public static final Transition CLOSE_INITIALISED = new Transition(State.INITIALISED, State.CLOSING, Event.BEFORE_CLOSE); + public static final Transition CLOSE_ACTIVATING = new Transition(State.ACTIVATING, State.CLOSING, Event.BEFORE_CLOSE); public static final Transition CLOSE_ACTIVE = new Transition(State.ACTIVE, State.CLOSING, Event.BEFORE_CLOSE); public static final Transition CLOSE_QUIESCED = new Transition(State.QUIESCED, State.CLOSING, Event.BEFORE_CLOSE); public static final Transition CLOSE_COMPLETE = new Transition(State.CLOSING, State.CLOSED, Event.AFTER_CLOSE); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/DaemonThreadFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/DaemonThreadFactory.java new file mode 100644 index 0000000000..4f1f830fd0 --- /dev/null +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/DaemonThreadFactory.java @@ -0,0 +1,40 @@ +/* + * + * 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.util; + +import java.util.concurrent.ThreadFactory; + +public final class DaemonThreadFactory implements ThreadFactory +{ + private String _threadName; + public DaemonThreadFactory(String threadName) + { + _threadName = threadName; + } + + @Override + public Thread newThread(Runnable r) + { + Thread thread = new Thread(r, _threadName); + thread.setDaemon(true); + return thread; + } +}
\ No newline at end of file diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/MapValueConverter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/MapValueConverter.java index 3543ce3bcf..b759bd5dc4 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/MapValueConverter.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/MapValueConverter.java @@ -321,21 +321,7 @@ public class MapValueConverter else if (typeObject instanceof ParameterizedType) { ParameterizedType parameterizedType= (ParameterizedType)typeObject; - Type type = parameterizedType.getRawType(); - if (type == Set.class) - { - Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); - if (actualTypeArguments.length != 1) - { - throw new IllegalArgumentException("Set type argument is not specified"); - } - Class<?> classObject = (Class<?>)actualTypeArguments[0]; - value = toSet(rawValue, classObject, attributeName); - } - else - { - throw new IllegalArgumentException("Conversion into " + parameterizedType + " is not yet supported"); - } + value = convertParameterizedType(rawValue, parameterizedType, attributeName); } else { @@ -352,6 +338,62 @@ public class MapValueConverter return attributes; } + private static Object convertParameterizedType(Object rawValue, ParameterizedType parameterizedType, String attributeName) + { + Type type = parameterizedType.getRawType(); + Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); + Object convertedValue; + if (type == Set.class) + { + if (actualTypeArguments.length != 1) + { + throw new IllegalArgumentException("Unexpected number of Set type arguments " + actualTypeArguments.length); + } + Class<?> classObject = (Class<?>)actualTypeArguments[0]; + convertedValue = toSet(rawValue, classObject, attributeName); + } + else if (type == Map.class) + { + if (actualTypeArguments.length != 2) + { + throw new IllegalArgumentException("Unexpected number of Map type arguments " + actualTypeArguments.length); + } + Class<?> keyClassObject = (Class<?>)actualTypeArguments[0]; + Class<?> valueClassObject = (Class<?>)actualTypeArguments[1]; + convertedValue = toMap(rawValue, keyClassObject, valueClassObject, attributeName); + } + else + { + throw new IllegalArgumentException("Conversion into " + parameterizedType + " is not yet supported"); + } + return convertedValue; + } + + private static <K,V> Map<K, V> toMap(Object rawValue, Class<K> keyClassObject, Class<V> valueClassObject, String attributeName) + { + if (rawValue == null) + { + return null; + } + if (rawValue instanceof Map) + { + Map<K, V> convertedMap = new HashMap<K, V>(); + Map<?, ?> rawMap = (Map<?,?>)rawValue; + + for (Map.Entry<?, ?> entry : rawMap.entrySet()) + { + K convertedKey = convert(entry.getKey(), keyClassObject, attributeName + " (map key)"); + V convertedValue = convert(entry.getValue(), valueClassObject, attributeName + " (map value)"); + convertedMap.put(convertedKey, convertedValue); + } + return convertedMap; + } + else + { + throw new IllegalArgumentException("rawValue is not of unexpected type Map, was : " + rawValue.getClass()); + } + } + public static <T> Set<T> toSet(Object rawValue, Class<T> setItemClass, String attributeName) { if (rawValue == null) @@ -361,7 +403,7 @@ public class MapValueConverter HashSet<T> set = new HashSet<T>(); if (rawValue instanceof Iterable) { - Iterable<?> iterable = (Iterable<?>)rawValue; + Iterable<?> iterable = (Iterable<?>)rawValue; for (Object object : iterable) { T converted = convert(object, setItemClass, attributeName); @@ -409,6 +451,10 @@ public class MapValueConverter { value = toEnum(attributeName, rawValue, (Class<Enum>) classObject); } + else if (classObject == Object.class) + { + value = rawValue; + } else { throw new IllegalArgumentException("Cannot convert '" + rawValue + "' of type '" + rawValue.getClass() diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java index a4719f6058..3ffa34f4fa 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java @@ -24,7 +24,6 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.BlockingQueue; @@ -32,7 +31,6 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import org.apache.commons.configuration.ConfigurationException; import org.apache.log4j.Logger; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.server.configuration.updater.TaskExecutor; @@ -41,9 +39,6 @@ import org.apache.qpid.server.exchange.ExchangeImpl; import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.model.LifetimePolicy; import org.apache.qpid.server.model.Queue; -import org.apache.qpid.server.configuration.ExchangeConfiguration; -import org.apache.qpid.server.configuration.QueueConfiguration; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.connection.ConnectionRegistry; import org.apache.qpid.server.connection.IConnectionRegistry; import org.apache.qpid.server.exchange.DefaultExchangeFactory; @@ -75,7 +70,6 @@ import org.apache.qpid.server.store.Event; import org.apache.qpid.server.store.EventListener; import org.apache.qpid.server.txn.DtxRegistry; import org.apache.qpid.server.util.MapValueConverter; -import org.apache.qpid.server.util.ServerScopedRuntimeException; public abstract class AbstractVirtualHost implements VirtualHost, IConnectionRegistry.RegistryChangeListener, EventListener { @@ -97,8 +91,6 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg private final SecurityManager _securityManager; - private final VirtualHostConfiguration _vhostConfig; - private final QueueRegistry _queueRegistry; private final ExchangeRegistry _exchangeRegistry; @@ -131,23 +123,11 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg public AbstractVirtualHost(VirtualHostRegistry virtualHostRegistry, StatisticsGatherer brokerStatisticsGatherer, SecurityManager parentSecurityManager, - VirtualHostConfiguration hostConfig, org.apache.qpid.server.model.VirtualHost virtualHost) { - if (hostConfig == null) - { - throw new IllegalArgumentException("HostConfig cannot be null"); - } - - if (hostConfig.getName() == null || hostConfig.getName().length() == 0) - { - throw new IllegalArgumentException("Illegal name (" + hostConfig.getName() + ") for virtualhost."); - } - _virtualHostRegistry = virtualHostRegistry; _brokerStatisticsGatherer = brokerStatisticsGatherer; - _vhostConfig = hostConfig; - _name = _vhostConfig.getName(); + _name = virtualHost.getName(); _dtxRegistry = new DtxRegistry(); _model = virtualHost; _eventLogger = virtualHostRegistry.getEventLogger(); @@ -156,12 +136,12 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg _eventLogger.message(VirtualHostMessages.CREATED(_name)); - _securityManager = new SecurityManager(parentSecurityManager, _vhostConfig.getConfig().getString("security.acl"), _name); + _securityManager = new SecurityManager(parentSecurityManager, virtualHost.getSecurityAcl(), _name); _connectionRegistry = new ConnectionRegistry(); _connectionRegistry.addRegistryChangeListener(this); - _houseKeepingTasks = new ScheduledThreadPoolExecutor(_vhostConfig.getHouseKeepingThreadCount()); + _houseKeepingTasks = new ScheduledThreadPoolExecutor(virtualHost.getHouseKeepingThreadCount()); _queueRegistry = new DefaultQueueRegistry(this); @@ -176,7 +156,7 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg initialiseStatistics(); - initialiseStorage(hostConfig, virtualHost); + initialiseStorage(virtualHost); getMessageStore().addEventListener(this, Event.PERSISTENT_MESSAGE_SIZE_OVERFULL); getMessageStore().addEventListener(this, Event.PERSISTENT_MESSAGE_SIZE_UNDERFULL); @@ -192,19 +172,13 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg } } - abstract protected void initialiseStorage(VirtualHostConfiguration hostConfig, - org.apache.qpid.server.model.VirtualHost virtualHost); + abstract protected void initialiseStorage(org.apache.qpid.server.model.VirtualHost<?> virtualHost); public IConnectionRegistry getConnectionRegistry() { return _connectionRegistry; } - public VirtualHostConfiguration getConfiguration() - { - return _vhostConfig; - } - public UUID getId() { return _id; @@ -306,135 +280,11 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg } - protected void initialiseModel(VirtualHostConfiguration config) + protected void initialiseModel() { - _logger.debug("Loading configuration for virtualhost: " + config.getName()); - + _logger.debug("Loading configuration for virtualhost: " + _model.getName()); _exchangeRegistry.initialise(_exchangeFactory); - - List<String> exchangeNames = config.getExchanges(); - - for (String exchangeName : exchangeNames) - { - try - { - configureExchange(config.getExchangeConfiguration(exchangeName)); - } - catch (UnknownExchangeException e) - { - throw new ServerScopedRuntimeException("Could not configure exchange " + exchangeName, e); - } - catch (ReservedExchangeNameException e) - { - throw new ServerScopedRuntimeException("Could not configure exchange " + exchangeName, e); - } - catch (AMQUnknownExchangeType e) - { - throw new ServerScopedRuntimeException("Could not configure exchange " + exchangeName, e); - } - } - - String[] queueNames = config.getQueueNames(); - - for (Object queueNameObj : queueNames) - { - String queueName = String.valueOf(queueNameObj); - try - { - configureQueue(config.getQueueConfiguration(queueName)); - } - catch (ConfigurationException e) - { - throw new ServerScopedRuntimeException("Could not configure queue " + queueName, e); - } - } - } - - private void configureExchange(ExchangeConfiguration exchangeConfiguration) - throws UnknownExchangeException, ReservedExchangeNameException, - AMQUnknownExchangeType - { - boolean durable = exchangeConfiguration.getDurable(); - boolean autodelete = exchangeConfiguration.getAutoDelete(); - try - { - Map<String,Object> attributes = new HashMap<String, Object>(); - - attributes.put(org.apache.qpid.server.model.Exchange.ID, null); - attributes.put(org.apache.qpid.server.model.Exchange.NAME, exchangeConfiguration.getName()); - attributes.put(org.apache.qpid.server.model.Exchange.TYPE, exchangeConfiguration.getType()); - attributes.put(org.apache.qpid.server.model.Exchange.DURABLE, durable); - attributes.put(org.apache.qpid.server.model.Exchange.LIFETIME_POLICY, - autodelete ? LifetimePolicy.DELETE_ON_NO_LINKS : LifetimePolicy.PERMANENT); - attributes.put(org.apache.qpid.server.model.Exchange.ALTERNATE_EXCHANGE, null); - ExchangeImpl newExchange = createExchange(attributes); - } - catch(ExchangeExistsException e) - { - _logger.info("Exchange " + exchangeConfiguration.getName() + " already defined. Configuration in XML file ignored"); - } - - } - - private void configureQueue(QueueConfiguration queueConfiguration) - throws ConfigurationException - { - AMQQueue queue = _queueFactory.createAMQQueueImpl(queueConfiguration); - String queueName = queue.getName(); - - if (queue.isDurable()) - { - DurableConfigurationStoreHelper.createQueue(getDurableConfigurationStore(), queue); - } - - //get the exchange name (returns empty String if none was specified) - String exchangeName = queueConfiguration.getExchange(); - - - if(ExchangeDefaults.DEFAULT_EXCHANGE_NAME.equals(exchangeName)) - { - //get routing keys in configuration (returns empty list if none are defined) - List<?> routingKeys = queueConfiguration.getRoutingKeys(); - if(!(routingKeys.isEmpty() || (routingKeys.size()==1 && routingKeys.contains(queueName)))) - { - throw new ConfigurationException("Attempt to bind queue '" + queueName + "' with binding key(s) " + - routingKeys + " without specifying an exchange"); - } - } - else - { - ExchangeImpl exchange = _exchangeRegistry.getExchange(exchangeName); - if (exchange == null) - { - throw new ConfigurationException("Attempt to bind queue '" + queueName + "' to unknown exchange:" + exchangeName); - } - - //get routing keys in configuration (returns empty list if none are defined) - List<?> routingKeys = queueConfiguration.getRoutingKeys(); - - for (Object routingKeyNameObj : routingKeys) - { - String routingKey = String.valueOf(routingKeyNameObj); - - configureBinding(queue, exchange, routingKey, (Map) queueConfiguration.getBindingArguments(routingKey)); - } - - if (!routingKeys.contains(queueName)) - { - //bind the queue to the named exchange using its name - configureBinding(queue, exchange, queueName, null); - } - } - } - - private void configureBinding(AMQQueue queue, ExchangeImpl exchange, String routingKey, Map<String,Object> arguments) - { - if (_logger.isInfoEnabled()) - { - _logger.info("Binding queue:" + queue + " with routing key '" + routingKey + "' to exchange:" + exchange.getName()); - } - exchange.addBinding(routingKey, queue, arguments); } public String getName() @@ -907,7 +757,7 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg try { - initialiseHouseKeeping(_vhostConfig.getHousekeepingCheckPeriod()); + initialiseHouseKeeping(_model.getHousekeepingCheckPeriod()); finalState = State.ACTIVE; } finally @@ -981,10 +831,10 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg } try { - session.checkTransactionStatus(_vhostConfig.getTransactionTimeoutOpenWarn(), - _vhostConfig.getTransactionTimeoutOpenClose(), - _vhostConfig.getTransactionTimeoutIdleWarn(), - _vhostConfig.getTransactionTimeoutIdleClose()); + session.checkTransactionStatus(_model.getStoreTransactionOpenTimeoutWarn(), + _model.getStoreTransactionOpenTimeoutClose(), + _model.getStoreTransactionIdleTimeoutWarn(), + _model.getStoreTransactionIdleTimeoutClose()); } catch (Exception e) { _logger.error("Exception in housekeeping for connection: " + connection.toString(), e); @@ -1039,49 +889,55 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg @Override public long getDefaultAlertThresholdMessageAge() { - return getConfiguration().getMaximumMessageAge(); + return _model.getQueue_alertThresholdMessageAge(); } @Override public long getDefaultAlertThresholdMessageSize() { - return getConfiguration().getMaximumMessageSize(); + return _model.getQueue_alertThresholdMessageSize(); } @Override public long getDefaultAlertThresholdQueueDepthMessages() { - return getConfiguration().getMaximumMessageCount(); + return _model.getQueue_alertThresholdQueueDepthMessages(); } @Override public long getDefaultAlertThresholdQueueDepthBytes() { - return getConfiguration().getMaximumQueueDepth(); + return _model.getQueue_alertThresholdQueueDepthBytes(); } @Override public long getDefaultAlertRepeatGap() { - return getConfiguration().getMinimumAlertRepeatGap(); + return _model.getQueue_alertRepeatGap(); } @Override public long getDefaultQueueFlowControlSizeBytes() { - return getConfiguration().getCapacity(); + return _model.getQueue_flowControlSizeBytes(); } @Override public long getDefaultQueueFlowResumeSizeBytes() { - return getConfiguration().getFlowResumeCapacity(); + return _model.getQueue_flowResumeSizeBytes(); } @Override public int getDefaultMaximumDeliveryAttempts() { - return getConfiguration().getMaxDeliveryCount(); + return _model.getQueue_maximumDeliveryAttempts(); + } + + @Override + public boolean getDefaultDeadLetterQueueEnabled() + { + return _model.isQueue_deadLetterQueueEnabled(); } @Override diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHost.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHost.java index 9b576bf41f..be6cc52981 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHost.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHost.java @@ -19,17 +19,17 @@ package org.apache.qpid.server.virtualhost;/* * */ -import org.apache.qpid.server.configuration.VirtualHostConfiguration; +import java.util.Map; + import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.plugin.MessageStoreFactory; import org.apache.qpid.server.stats.StatisticsGatherer; import org.apache.qpid.server.store.DurableConfigurationRecoverer; import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.DurableConfigurationStoreCreator; import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.MessageStoreCreator; import org.apache.qpid.server.store.OperationalLoggingListener; -import org.apache.qpid.server.util.ServerScopedRuntimeException; public class StandardVirtualHost extends AbstractVirtualHost { @@ -40,54 +40,17 @@ public class StandardVirtualHost extends AbstractVirtualHost StandardVirtualHost(VirtualHostRegistry virtualHostRegistry, StatisticsGatherer brokerStatisticsGatherer, org.apache.qpid.server.security.SecurityManager parentSecurityManager, - VirtualHostConfiguration hostConfig, VirtualHost virtualHost) + VirtualHost virtualHost) { - super(virtualHostRegistry, brokerStatisticsGatherer, parentSecurityManager, hostConfig, virtualHost); + super(virtualHostRegistry, brokerStatisticsGatherer, parentSecurityManager, virtualHost); } - private MessageStore initialiseMessageStore(VirtualHostConfiguration hostConfig, VirtualHost virtualHost) + private MessageStore initialiseMessageStore(String storeType) { - final Object storeTypeAttr = virtualHost.getAttribute(VirtualHost.STORE_TYPE); - String storeType = storeTypeAttr == null ? null : String.valueOf(storeTypeAttr); - MessageStore messageStore = null; - if (storeType == null) - { - try - { - final Class<?> clazz = Class.forName(hostConfig.getMessageStoreClass()); - final Object o = clazz.newInstance(); - - if (!(o instanceof MessageStore)) - { - throw new ClassCastException(clazz + " does not implement " + MessageStore.class); - } - - messageStore = (MessageStore) o; - } - catch (ClassNotFoundException e) - { - throw new ServerScopedRuntimeException("Failed to fina virtual host message store implementation, " + - "check the classpath and the configuration", e); - } - catch (InstantiationException e) - { - throw new ServerScopedRuntimeException("Failed to initialise virtual host store, " + - "check the configuration", e); - } - catch (IllegalAccessException e) - { - throw new ServerScopedRuntimeException("Failed to initialise virtual host store, " + - "check the configuration", e); - } - } - else - { - messageStore = new MessageStoreCreator().createMessageStore(storeType); - } + MessageStore messageStore = MessageStoreFactory.FACTORY_LOADER.get(storeType).createMessageStore(); - final MessageStoreLogSubject storeLogSubject = new MessageStoreLogSubject(getName(), messageStore.getClass().getSimpleName()); OperationalLoggingListener.listen(messageStore, storeLogSubject, getEventLogger()); @@ -95,11 +58,9 @@ public class StandardVirtualHost extends AbstractVirtualHost return messageStore; } - private DurableConfigurationStore initialiseConfigurationStore(VirtualHost virtualHost) + private DurableConfigurationStore initialiseConfigurationStore(String storeType) { DurableConfigurationStore configurationStore; - final Object storeTypeAttr = virtualHost.getAttribute(VirtualHost.CONFIG_STORE_TYPE); - String storeType = storeTypeAttr == null ? null : String.valueOf(storeTypeAttr); if(storeType != null) { @@ -118,11 +79,15 @@ public class StandardVirtualHost extends AbstractVirtualHost } - protected void initialiseStorage(VirtualHostConfiguration hostConfig, VirtualHost virtualHost) + protected void initialiseStorage(VirtualHost virtualHost) { - _messageStore = initialiseMessageStore(hostConfig, virtualHost); + Map<String, Object> messageStoreSettings = virtualHost.getMessageStoreSettings(); + String storeType = (String) messageStoreSettings.get(MessageStore.STORE_TYPE); + _messageStore = initialiseMessageStore(storeType); - _durableConfigurationStore = initialiseConfigurationStore(virtualHost); + Map<String, Object> configurationStoreSettings = virtualHost.getConfigurationStoreSettings(); + String configurationStoreType = configurationStoreSettings == null ? null : (String) configurationStoreSettings.get(DurableConfigurationStore.STORE_TYPE); + _durableConfigurationStore = initialiseConfigurationStore(configurationStoreType); DurableConfigurationRecoverer configRecoverer = new DurableConfigurationRecoverer(getName(), getDurableConfigurationRecoverers(), @@ -132,7 +97,7 @@ public class StandardVirtualHost extends AbstractVirtualHost VirtualHostConfigRecoveryHandler recoveryHandler = new VirtualHostConfigRecoveryHandler(this); _messageStore.configureMessageStore(virtualHost, recoveryHandler, recoveryHandler); - initialiseModel(hostConfig); + initialiseModel(); _messageStore.activate(); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHostFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHostFactory.java index c28bcb977f..7cc8eaa20c 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHostFactory.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHostFactory.java @@ -19,16 +19,13 @@ package org.apache.qpid.server.virtualhost;/* * */ -import java.util.LinkedHashMap; +import java.util.Collection; import java.util.Map; -import org.apache.commons.configuration.Configuration; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; -import org.apache.qpid.server.model.adapter.VirtualHostAdapter; + import org.apache.qpid.server.plugin.MessageStoreFactory; import org.apache.qpid.server.plugin.VirtualHostFactory; import org.apache.qpid.server.stats.StatisticsGatherer; -import org.apache.qpid.server.store.MessageStoreConstants; -import org.apache.qpid.server.store.MessageStoreCreator; +import org.apache.qpid.server.store.MessageStore; public class StandardVirtualHostFactory implements VirtualHostFactory { @@ -45,74 +42,48 @@ public class StandardVirtualHostFactory implements VirtualHostFactory public VirtualHost createVirtualHost(VirtualHostRegistry virtualHostRegistry, StatisticsGatherer brokerStatisticsGatherer, org.apache.qpid.server.security.SecurityManager parentSecurityManager, - VirtualHostConfiguration hostConfig, org.apache.qpid.server.model.VirtualHost virtualHost) { - return new StandardVirtualHost(virtualHostRegistry, brokerStatisticsGatherer, parentSecurityManager, hostConfig, virtualHost); + return new StandardVirtualHost(virtualHostRegistry, brokerStatisticsGatherer, parentSecurityManager, virtualHost); } - public static final String STORE_TYPE_ATTRIBUTE = org.apache.qpid.server.model.VirtualHost.STORE_TYPE; - public static final String STORE_PATH_ATTRIBUTE = org.apache.qpid.server.model.VirtualHost.STORE_PATH; - @Override public void validateAttributes(Map<String, Object> attributes) { + @SuppressWarnings("unchecked") + Map<String, Object> messageStoreSettings = (Map<String, Object>)attributes.get(org.apache.qpid.server.model.VirtualHost.MESSAGE_STORE_SETTINGS); + if (messageStoreSettings == null) + { + throw new IllegalArgumentException("Attribute '"+ org.apache.qpid.server.model.VirtualHost.MESSAGE_STORE_SETTINGS + "' is required."); + } + + Object storeType = messageStoreSettings.get(MessageStore.STORE_TYPE); // need store type and path - Object storeType = attributes.get(STORE_TYPE_ATTRIBUTE); - if(!(storeType instanceof String)) - { + Collection<String> knownTypes = MessageStoreFactory.FACTORY_LOADER.getSupportedTypes(); - throw new IllegalArgumentException("Attribute '"+ STORE_TYPE_ATTRIBUTE - +"' is required and must be of type String."); - } - final MessageStoreCreator storeCreator = new MessageStoreCreator(); - if(!storeCreator.isValidType((String)storeType)) + if (storeType == null) { - throw new IllegalArgumentException("Attribute '"+ STORE_TYPE_ATTRIBUTE - +"' has value '"+storeType+"' which is not one of the valid values: " - + storeCreator.getStoreTypes() + "."); - + throw new IllegalArgumentException("Setting '"+ MessageStore.STORE_TYPE + +"' is required in attribute " + org.apache.qpid.server.model.VirtualHost.MESSAGE_STORE_SETTINGS + ". Known types are : " + knownTypes); } - - for(MessageStoreFactory factory : storeCreator.getFactories()) + else if (!(storeType instanceof String)) { - if(factory.getType().equalsIgnoreCase((String)storeType)) - { - factory.validateAttributes(attributes); - } + throw new IllegalArgumentException("Setting '"+ MessageStore.STORE_TYPE + +"' is required and must be of type String. " + +"Known types are : " + knownTypes); } - } - - @Override - public Map<String,Object> createVirtualHostConfiguration(VirtualHostAdapter virtualHostAdapter) - { - Map<String,Object> convertedMap = new LinkedHashMap<String, Object>(); - convertedMap.put("store.type", virtualHostAdapter.getAttribute(org.apache.qpid.server.model.VirtualHost.STORE_TYPE)); - convertedMap.put("store.environment-path", virtualHostAdapter.getAttribute(org.apache.qpid.server.model.VirtualHost.STORE_PATH)); - - return convertedMap; - } - - @Override - public Map<String, Object> convertVirtualHostConfiguration(Configuration configuration) - { - Map<String,Object> convertedMap = new LinkedHashMap<String, Object>(); - Configuration storeConfiguration = configuration.subset("store"); - convertedMap.put(org.apache.qpid.server.model.VirtualHost.STORE_TYPE, storeConfiguration.getString("type")); - convertedMap.put(org.apache.qpid.server.model.VirtualHost.STORE_PATH, storeConfiguration.getString(MessageStoreConstants.ENVIRONMENT_PATH_PROPERTY)); - - convertedMap.put(MessageStoreConstants.OVERFULL_SIZE_ATTRIBUTE, storeConfiguration.getString(MessageStoreConstants.OVERFULL_SIZE_PROPERTY)); - convertedMap.put(MessageStoreConstants.UNDERFULL_SIZE_ATTRIBUTE, storeConfiguration.getString(MessageStoreConstants.UNDERFULL_SIZE_PROPERTY)); - - for(MessageStoreFactory mf : new MessageStoreCreator().getFactories()) + MessageStoreFactory factory = MessageStoreFactory.FACTORY_LOADER.get((String)storeType); + if(factory == null) { - convertedMap.putAll(mf.convertStoreConfiguration(storeConfiguration)); + throw new IllegalArgumentException("Setting '"+ MessageStore.STORE_TYPE + +"' has value '" + storeType + "' which is not one of the valid values: " + + "Known types are : " + knownTypes); } - return convertedMap; + factory.validateAttributes(attributes); } } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java index a06056de8f..f113abb25a 100755 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java @@ -28,7 +28,6 @@ import java.util.concurrent.ScheduledFuture; import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.exchange.AMQUnknownExchangeType; import org.apache.qpid.common.Closeable; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.connection.IConnectionRegistry; import org.apache.qpid.server.exchange.ExchangeImpl; import org.apache.qpid.server.logging.EventLogger; @@ -49,8 +48,6 @@ public interface VirtualHost extends DurableConfigurationStore.Source, Closeable { IConnectionRegistry getConnectionRegistry(); - VirtualHostConfiguration getConfiguration(); - String getName(); AMQQueue getQueue(String name); @@ -137,6 +134,8 @@ public interface VirtualHost extends DurableConfigurationStore.Source, Closeable int getDefaultMaximumDeliveryAttempts(); + boolean getDefaultDeadLetterQueueEnabled(); + TaskExecutor getTaskExecutor(); org.apache.qpid.server.model.VirtualHost getModel(); diff --git a/qpid/java/broker-core/src/main/resources/initial-config.json b/qpid/java/broker-core/src/main/resources/initial-config.json index 7173433aa8..efc98f6ac8 100644 --- a/qpid/java/broker-core/src/main/resources/initial-config.json +++ b/qpid/java/broker-core/src/main/resources/initial-config.json @@ -21,7 +21,7 @@ { "name": "Broker", "storeVersion": 1, - "modelVersion": "1.2", + "modelVersion": "1.4", "defaultVirtualHost" : "default", "authenticationproviders" : [ { "name" : "passwordFile", @@ -55,8 +55,10 @@ "virtualhosts" : [ { "name" : "default", "type" : "STANDARD", - "storeType" : "DERBY", - "storePath" : "${qpid.work_dir}/derbystore/default" + "messageStoreSettings" : { + "storeType" : "DERBY", + "storePath" : "${qpid.work_dir}/derbystore/default" + } } ], "plugins" : [ { "pluginType" : "MANAGEMENT-HTTP", diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/QueueConfigurationTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/QueueConfigurationTest.java deleted file mode 100644 index 2c3420a718..0000000000 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/QueueConfigurationTest.java +++ /dev/null @@ -1,269 +0,0 @@ -/* - * - * 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.configuration; - -import static org.mockito.Mockito.when; - -import java.util.Collections; -import junit.framework.TestCase; -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.PropertiesConfiguration; - -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.queue.QueueArgumentsConverter; -import org.apache.qpid.server.util.BrokerTestHelper; - -public class QueueConfigurationTest extends TestCase -{ - private VirtualHostConfiguration _emptyConf; - private PropertiesConfiguration _env; - private VirtualHostConfiguration _fullHostConf; - private Broker _broker; - - @Override - public void setUp() throws Exception - { - super.setUp(); - BrokerTestHelper.setUp(); - _broker = BrokerTestHelper.createBrokerMock(); - _env = new PropertiesConfiguration(); - _emptyConf = new VirtualHostConfiguration("test", _env, _broker); - - PropertiesConfiguration fullEnv = new PropertiesConfiguration(); - fullEnv.setProperty("queues.maximumMessageAge", 1); - fullEnv.setProperty("queues.maximumQueueDepth", 1); - fullEnv.setProperty("queues.maximumMessageSize", 1); - fullEnv.setProperty("queues.maximumMessageCount", 1); - fullEnv.setProperty("queues.minimumAlertRepeatGap", 1); - fullEnv.setProperty("queues.deadLetterQueues", true); - fullEnv.setProperty("queues.maximumDeliveryCount", 5); - - _fullHostConf = new VirtualHostConfiguration("test", fullEnv, _broker); - - } - - @Override - public void tearDown() throws Exception - { - BrokerTestHelper.tearDown(); - super.tearDown(); - } - - public void testMaxDeliveryCount() throws Exception - { - // broker MAXIMUM_DELIVERY_ATTEMPTS attribute is not set - when(_broker.getAttribute(Broker.QUEUE_MAXIMUM_DELIVERY_ATTEMPTS)).thenReturn(null); - - // Check default value - QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf); - assertEquals("Unexpected default server configuration for max delivery count ", 0, qConf.getMaxDeliveryCount()); - - // set broker MAXIMUM_DELIVERY_ATTEMPTS attribute to 2 - when(_broker.getAttribute(Broker.QUEUE_MAXIMUM_DELIVERY_ATTEMPTS)).thenReturn(2); - - // Check that queue inherits the MAXIMUM_DELIVERY_ATTEMPTS value from broker - qConf = new QueueConfiguration("test", _emptyConf); - assertEquals("Unexpected default server configuration for max delivery count ", 2, qConf.getMaxDeliveryCount()); - - // Check explicit value - VirtualHostConfiguration vhostConfig = overrideConfiguration("maximumDeliveryCount", 7); - qConf = new QueueConfiguration("test", vhostConfig); - assertEquals("Unexpected host configuration for max delivery count", 7, qConf.getMaxDeliveryCount()); - - // Check inherited value - qConf = new QueueConfiguration("test", _fullHostConf); - assertEquals("Unexpected queue configuration for max delivery count", 5, qConf.getMaxDeliveryCount()); - } - - /** - * Tests that the default setting for DLQ configuration is disabled, and verifies that it can be overridden - * at a broker or virtualhost level. - * @throws Exception - */ - public void testIsDeadLetterQueueEnabled() throws Exception - { - // enable dead letter queues broker wide - when(_broker.getAttribute(Broker.QUEUE_DEAD_LETTER_QUEUE_ENABLED)).thenReturn(true); - - // Check that queue inherits the broker setting - QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf); - assertTrue("Unexpected queue configuration for dead letter enabled attribute", qConf.isDeadLetterQueueEnabled()); - - // broker DEAD_LETTER_QUEUE_ENABLED is not set - when(_broker.getAttribute(Broker.QUEUE_DEAD_LETTER_QUEUE_ENABLED)).thenReturn(null); - - // Check that queue dead letter queue is not enabled - qConf = new QueueConfiguration("test", _emptyConf); - assertFalse("Unexpected queue configuration for dead letter enabled attribute", qConf.isDeadLetterQueueEnabled()); - - // Check explicit value - VirtualHostConfiguration vhostConfig = overrideConfiguration("deadLetterQueues", true); - qConf = new QueueConfiguration("test", vhostConfig); - assertTrue("Unexpected queue configuration for dead letter enabled attribute", qConf.isDeadLetterQueueEnabled()); - - // Check inherited value - qConf = new QueueConfiguration("test", _fullHostConf); - assertTrue("Unexpected queue configuration for dead letter enabled attribute", qConf.isDeadLetterQueueEnabled()); - } - - public void testGetMaximumMessageAge() throws ConfigurationException - { - // Check default value - QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf); - assertEquals(0, qConf.getMaximumMessageAge()); - - // Check explicit value - VirtualHostConfiguration vhostConfig = overrideConfiguration("maximumMessageAge", 2); - - qConf = new QueueConfiguration("test", vhostConfig); - assertEquals(2, qConf.getMaximumMessageAge()); - - } - - public void testGetMaximumQueueDepth() throws ConfigurationException - { - // Check default value - QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf); - assertEquals(0, qConf.getMaximumQueueDepth()); - - // Check explicit value - VirtualHostConfiguration vhostConfig = overrideConfiguration("maximumQueueDepth", 2); - qConf = new QueueConfiguration("test", vhostConfig); - assertEquals(2, qConf.getMaximumQueueDepth()); - - } - - public void testGetMaximumMessageSize() throws ConfigurationException - { - // Check default value - QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf); - assertEquals(0, qConf.getMaximumMessageSize()); - - // Check explicit value - VirtualHostConfiguration vhostConfig = overrideConfiguration("maximumMessageSize", 2); - qConf = new QueueConfiguration("test", vhostConfig); - assertEquals(2, qConf.getMaximumMessageSize()); - - } - - public void testGetMaximumMessageCount() throws ConfigurationException - { - // Check default value - QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf); - assertEquals(0, qConf.getMaximumMessageCount()); - - // Check explicit value - VirtualHostConfiguration vhostConfig = overrideConfiguration("maximumMessageCount", 2); - qConf = new QueueConfiguration("test", vhostConfig); - assertEquals(2, qConf.getMaximumMessageCount()); - - } - - public void testGetMinimumAlertRepeatGap() throws Exception - { - QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf); - - // Check default value - qConf = new QueueConfiguration("test", _emptyConf); - assertEquals(0, qConf.getMinimumAlertRepeatGap()); - - // Check explicit value - VirtualHostConfiguration vhostConfig = overrideConfiguration("minimumAlertRepeatGap", 2); - qConf = new QueueConfiguration("test", vhostConfig); - assertEquals(2, qConf.getMinimumAlertRepeatGap()); - - } - - public void testSortQueueConfiguration() throws ConfigurationException - { - //Check default value - QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf); - assertNull(qConf.getQueueSortKey()); - - // Check explicit value - final VirtualHostConfiguration vhostConfig = overrideConfiguration("sortKey", "test-sort-key"); - qConf = new QueueConfiguration("test", vhostConfig); - assertEquals("test-sort-key", qConf.getQueueSortKey()); - } - - public void testQueueDescription() throws ConfigurationException - { - //Check default value - QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf); - assertNull(qConf.getDescription()); - - // Check explicit value - final VirtualHostConfiguration vhostConfig = overrideConfiguration("description", "mydescription"); - qConf = new QueueConfiguration("test", vhostConfig); - assertEquals("mydescription", qConf.getDescription()); - } - - - public void testQueueSingleArgument() throws ConfigurationException - { - //Check default value - QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf); - assertTrue(qConf.getArguments().isEmpty()); - - // Check explicit value - final VirtualHostConfiguration vhostConfig = overrideConfiguration("argument", QueueArgumentsConverter.QPID_GROUP_HEADER_KEY + "=mykey"); - qConf = new QueueConfiguration("test", vhostConfig); - assertEquals(Collections.singletonMap(QueueArgumentsConverter.QPID_GROUP_HEADER_KEY,"mykey"), qConf.getArguments()); - } - - - public void testQueueMultipleArguments() throws ConfigurationException - { - //Check default value - QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf); - assertTrue(qConf.getArguments().isEmpty()); - - - PropertiesConfiguration queueConfig = new PropertiesConfiguration(); - queueConfig.addProperty("queues.queue.test.argument", QueueArgumentsConverter.QPID_GROUP_HEADER_KEY + "=mykey"); - queueConfig.addProperty("queues.queue.test.argument", QueueArgumentsConverter.QPID_SHARED_MSG_GROUP + "=1"); - - CompositeConfiguration config = new CompositeConfiguration(); - config.addConfiguration(_fullHostConf.getConfig()); - config.addConfiguration(queueConfig); - - final VirtualHostConfiguration vhostConfig = new VirtualHostConfiguration("test", config, _broker);; - qConf = new QueueConfiguration("test", vhostConfig); - assertEquals(2, qConf.getArguments().size()); - assertEquals("mykey", qConf.getArguments().get(QueueArgumentsConverter.QPID_GROUP_HEADER_KEY)); - assertEquals("1", qConf.getArguments().get(QueueArgumentsConverter.QPID_SHARED_MSG_GROUP)); - } - - - private VirtualHostConfiguration overrideConfiguration(String property, Object value) - throws ConfigurationException - { - PropertiesConfiguration queueConfig = new PropertiesConfiguration(); - queueConfig.setProperty("queues.queue.test." + property, value); - - CompositeConfiguration config = new CompositeConfiguration(); - config.addConfiguration(_fullHostConf.getConfig()); - config.addConfiguration(queueConfig); - - return new VirtualHostConfiguration("test", config, _broker); - } -} diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java deleted file mode 100644 index bd11f7192b..0000000000 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java +++ /dev/null @@ -1,410 +0,0 @@ -/* - * 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.configuration; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; - -import org.apache.qpid.server.logging.EventLogger; -import org.apache.qpid.server.logging.NullMessageLogger; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.queue.PriorityQueue; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.store.TestableMemoryMessageStore; -import org.apache.qpid.server.util.BrokerTestHelper; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.virtualhost.VirtualHostRegistry; -import org.apache.qpid.test.utils.QpidTestCase; - -public class VirtualHostConfigurationTest extends QpidTestCase -{ - private VirtualHostRegistry _virtualHostRegistry; - private XMLConfiguration _configXml; - private Broker _broker; - - @Override - public void setUp() throws Exception - { - super.setUp(); - BrokerTestHelper.setUp(); - _configXml = new XMLConfiguration(); - _configXml.addProperty("virtualhosts.virtualhost(-1).name", getName()); - _configXml.addProperty("virtualhosts.virtualhost(-1)."+getName()+".store.class", TestableMemoryMessageStore.class.getName()); - EventLogger eventLogger = new EventLogger(); - _virtualHostRegistry = new VirtualHostRegistry(eventLogger); - _broker = mock(Broker.class); - when(_broker.getAttribute(Broker.VIRTUALHOST_HOUSEKEEPING_CHECK_PERIOD)).thenReturn(30000l); - } - - @Override - public void tearDown() throws Exception - { - try - { - if (_virtualHostRegistry != null) - { - _virtualHostRegistry.close(); - } - } - finally - { - BrokerTestHelper.tearDown(); - super.tearDown(); - } - } - - private XMLConfiguration getConfigXml() - { - return _configXml; - } - - private VirtualHost createVirtualHost(String hostName) throws Exception - { - Configuration config = getConfigXml().subset("virtualhosts.virtualhost." + XmlConfigurationUtilities.escapeTagName(hostName)); - VirtualHostConfiguration virtualHostConfiguration = new VirtualHostConfiguration(hostName, config, _broker); - return BrokerTestHelper.createVirtualHost(virtualHostConfiguration, _virtualHostRegistry); - } - - public void testQueuePriority() throws Exception - { - // Set up queue with 5 priorities - getConfigXml().addProperty("virtualhosts.virtualhost.testQueuePriority.queues(-1).queue(-1).name(-1)", - "atest"); - getConfigXml().addProperty("virtualhosts.virtualhost.testQueuePriority.queues.queue.atest(-1).exchange", - "amq.direct"); - getConfigXml().addProperty("virtualhosts.virtualhost.testQueuePriority.queues.queue.atest.priorities", - "5"); - - // Set up queue with JMS style priorities - getConfigXml().addProperty("virtualhosts.virtualhost.testQueuePriority.queues(-1).queue(-1).name(-1)", - "ptest"); - getConfigXml().addProperty("virtualhosts.virtualhost.testQueuePriority.queues.queue.ptest(-1).exchange", - "amq.direct"); - getConfigXml().addProperty("virtualhosts.virtualhost.testQueuePriority.queues.queue.ptest.priority", - "true"); - - // Set up queue with no priorities - getConfigXml().addProperty("virtualhosts.virtualhost.testQueuePriority.queues(-1).queue(-1).name(-1)", - "ntest"); - getConfigXml().addProperty("virtualhosts.virtualhost.testQueuePriority.queues.queue.ntest(-1).exchange", - "amq.direct"); - getConfigXml().addProperty("virtualhosts.virtualhost.testQueuePriority.queues.queue.ntest.priority", - "false"); - - VirtualHost vhost = createVirtualHost(getName()); - - // Check that atest was a priority queue with 5 priorities - AMQQueue atest = vhost.getQueue("atest"); - assertTrue(atest instanceof PriorityQueue); - assertEquals(5, ((PriorityQueue) atest).getPriorities()); - - // Check that ptest was a priority queue with 10 priorities - AMQQueue ptest = vhost.getQueue("ptest"); - assertTrue(ptest instanceof PriorityQueue); - assertEquals(10, ((PriorityQueue) ptest).getPriorities()); - - // Check that ntest wasn't a priority queue - AMQQueue ntest = vhost.getQueue("ntest"); - assertFalse(ntest instanceof PriorityQueue); - } - - public void testQueueAlerts() throws Exception - { - // Set up queue with 5 priorities - getConfigXml().addProperty("virtualhosts.virtualhost.testQueueAlerts.queues.exchange", "amq.topic"); - getConfigXml().addProperty("virtualhosts.virtualhost.testQueueAlerts.queues.maximumQueueDepth", "1"); - getConfigXml().addProperty("virtualhosts.virtualhost.testQueueAlerts.queues.maximumMessageSize", "2"); - getConfigXml().addProperty("virtualhosts.virtualhost.testQueueAlerts.queues.maximumMessageAge", "3"); - - getConfigXml().addProperty("virtualhosts.virtualhost.testQueueAlerts.queues(-1).queue(1).name(1)", "atest"); - getConfigXml().addProperty("virtualhosts.virtualhost.testQueueAlerts.queues.queue.atest(-1).exchange", "amq.direct"); - getConfigXml().addProperty("virtualhosts.virtualhost.testQueueAlerts.queues.queue.atest(-1).maximumQueueDepth", "4"); - getConfigXml().addProperty("virtualhosts.virtualhost.testQueueAlerts.queues.queue.atest(-1).maximumMessageSize", "5"); - getConfigXml().addProperty("virtualhosts.virtualhost.testQueueAlerts.queues.queue.atest(-1).maximumMessageAge", "6"); - - getConfigXml().addProperty("virtualhosts.virtualhost.testQueueAlerts.queues(-1).queue(-1).name(-1)", "btest"); - - VirtualHost vhost = createVirtualHost(getName()); - - // Check specifically configured values - AMQQueue aTest = vhost.getQueue("atest"); - assertEquals(4, aTest.getAlertThresholdQueueDepthBytes()); - assertEquals(5, aTest.getAlertThresholdMessageSize()); - assertEquals(6, aTest.getAlertThresholdMessageAge()); - - // Check default values - AMQQueue bTest = vhost.getQueue("btest"); - assertEquals(1, bTest.getAlertThresholdQueueDepthBytes()); - assertEquals(2, bTest.getAlertThresholdMessageSize()); - assertEquals(3, bTest.getAlertThresholdMessageAge()); - } - - public void testMaxDeliveryCount() throws Exception - { - // Set up vhosts and queues - getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + ".queues.maximumDeliveryCount", 5); - getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + ".queues(-1).queue(-1).name", "biggles"); - getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + ".queues.queue.biggles.maximumDeliveryCount", 4); - getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + ".queues(-1).queue(-1).name", "beetle"); - - VirtualHost test = createVirtualHost(getName()); - - // Enabled specifically - assertEquals("Test vhost MDC was configured as enabled", 5 ,test.getConfiguration().getMaxDeliveryCount()); - - // Enabled by test vhost default - assertEquals("beetle queue DLQ was configured as enabled", test.getConfiguration().getMaxDeliveryCount(), test.getConfiguration().getQueueConfiguration("beetle").getMaxDeliveryCount()); - - // Disabled specifically - assertEquals("Biggles queue DLQ was configured as disabled", 4, test.getConfiguration().getQueueConfiguration("biggles").getMaxDeliveryCount()); - } - - /** - * Tests the full set of configuration options for enabling DLQs in the broker configuration. - */ - public void testIsDeadLetterQueueEnabled() throws Exception - { - // Set up vhosts and queues - getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + ".queues.deadLetterQueues", "true"); - getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + ".queues(-1).queue(-1).name", "biggles"); - getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + ".queues.queue.biggles.deadLetterQueues", "false"); - getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + ".queues(-1).queue(-1).name", "beetle"); - - - getConfigXml().addProperty("virtualhosts.virtualhost.name", getName() + "Extra"); - getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + "Extra.queues(-1).queue(-1).name", "r2d2"); - getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + "Extra.queues.queue.r2d2.deadLetterQueues", "true"); - getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + "Extra.queues(-1).queue(-1).name", "c3p0"); - getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + "Extra.store.class", TestableMemoryMessageStore.class.getName()); - - VirtualHost test = createVirtualHost(getName()); - VirtualHost extra = createVirtualHost(getName() + "Extra"); - - // Enabled specifically - assertTrue("Test vhost DLQ was configured as enabled", test.getConfiguration().isDeadLetterQueueEnabled()); - assertTrue("r2d2 queue DLQ was configured as enabled", extra.getConfiguration().getQueueConfiguration("r2d2").isDeadLetterQueueEnabled()); - - // Enabled by test vhost default - assertTrue("beetle queue DLQ was configured as enabled", test.getConfiguration().getQueueConfiguration("beetle").isDeadLetterQueueEnabled()); - - // Disabled specifically - assertFalse("Biggles queue DLQ was configured as disabled", test.getConfiguration().getQueueConfiguration("biggles").isDeadLetterQueueEnabled()); - - // Using broker default of disabled - assertFalse("Extra vhost DLQ disabled, using broker default", extra.getConfiguration().isDeadLetterQueueEnabled()); - assertFalse("c3p0 queue DLQ was configured as disabled", extra.getConfiguration().getQueueConfiguration("c3p0").isDeadLetterQueueEnabled()); - - // Get queues - AMQQueue biggles = test.getQueue("biggles"); - AMQQueue beetle = test.getQueue("beetle"); - AMQQueue r2d2 = extra.getQueue("r2d2"); - AMQQueue c3p0 = extra.getQueue("c3p0"); - - // Disabled specifically for this queue, overriding virtualhost setting - assertNull("Biggles queue should not have alt exchange as DLQ should be configured as disabled: " + biggles.getAlternateExchange(), biggles.getAlternateExchange()); - - // Enabled for all queues on the virtualhost - assertNotNull("Beetle queue should have an alt exchange as DLQ should be enabled, using test vhost default", beetle.getAlternateExchange()); - - // Enabled specifically for this queue, overriding the default broker setting of disabled - assertNotNull("R2D2 queue should have an alt exchange as DLQ should be configured as enabled", r2d2.getAlternateExchange()); - - // Disabled by the default broker setting - assertNull("C3PO queue should not have an alt exchange as DLQ should be disabled, using broker default", c3p0.getAlternateExchange()); - } - - /** - * Test that the house keeping pool sizes is correctly processed - * - * @throws Exception - */ - public void testHouseKeepingThreadCount() throws Exception - { - int initialPoolSize = 10; - - getConfigXml().addProperty("virtualhosts.virtualhost.testHouseKeepingThreadCount.housekeeping.poolSize", - initialPoolSize); - - VirtualHost vhost = createVirtualHost(getName()); - - assertEquals("HouseKeeping PoolSize not set correctly.", - initialPoolSize, vhost.getHouseKeepingPoolSize()); - } - - /** - * Test that we can dynamically change the thread pool size - * - * @throws Exception - */ - public void testDynamicHouseKeepingPoolSizeChange() throws Exception - { - int initialPoolSize = 10; - - getConfigXml().addProperty("virtualhosts.virtualhost.testDynamicHouseKeepingPoolSizeChange.housekeeping.poolSize", - initialPoolSize); - - VirtualHost vhost = createVirtualHost(getName()); - - assertEquals("HouseKeeping PoolSize not set correctly.", - initialPoolSize, vhost.getHouseKeepingPoolSize()); - - vhost.setHouseKeepingPoolSize(1); - - assertEquals("HouseKeeping PoolSize not correctly change.", - 1, vhost.getHouseKeepingPoolSize()); - - } - - /** - * Tests that the old element security.authentication.name is rejected. This element - * was never supported properly as authentication is performed before the virtual host - * is considered. - */ - public void testSecurityAuthenticationNameRejected() throws Exception - { - getConfigXml().addProperty("virtualhosts.virtualhost.testSecurityAuthenticationNameRejected.security.authentication.name", - "testdb"); - - try - { - createVirtualHost(getName()); - fail("Exception not thrown"); - } - catch(ConfigurationException ce) - { - assertEquals("Incorrect error message", - "Validation error : security/authentication/name is no longer a supported element within the configuration xml." + - " It appears in virtual host definition : " + getName(), - ce.getMessage()); - } - } - - /* - * Tests that the old element housekeeping.expiredMessageCheckPeriod. ... (that was - * replaced by housekeeping.checkPeriod) is rejected. - */ - public void testExpiredMessageCheckPeriodRejected() throws Exception - { - getConfigXml().addProperty("virtualhosts.virtualhost.testExpiredMessageCheckPeriodRejected.housekeeping.expiredMessageCheckPeriod", - 5); - - try - { - createVirtualHost(getName()); - fail("Exception not thrown"); - } - catch (ConfigurationException ce) - { - assertEquals("Incorrect error message", - "Validation error : housekeeping/expiredMessageCheckPeriod must be replaced by housekeeping/checkPeriod." + - " It appears in virtual host definition : " + getName(), - ce.getMessage()); - } - } - - /* - * Tests that the queues with dots in the names are fully supported. The XML configuration - * had problems with handling the tags containing dots due to the design of the Apache Commons - * Configuration library. The dots need to be escaped when accessing the XML configuration. - */ - public void testDotsInQueueName() throws Exception - { - // Set up vhosts and queue - getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + ".queues(-1).queue(-1).name", "dot.in.a.name"); - // Add a single property which is inside the <dot.in.a.name> queue tag - the maximum delivery count - getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + ".queues.queue.dot..in..a..name.maximumDeliveryCount", 5); - - VirtualHost test = createVirtualHost(getName()); - - // Check, that the property stored within the <dot.in.a.name> tag has been properly loaded - assertEquals("queue with dots in its name has been properly loaded", 5, test.getConfiguration().getQueueConfiguration("dot.in.a.name").getMaxDeliveryCount()); - } - - /* - * Tests that the virtual hosts with dots in the names are fully supported. The XML - * configuration had problems with handling the tags containing dots due to the design - * of the Apache Commons Configuration library. The dots need to be escaped when - * accessing the XML configuration. - */ - public void testDotsInVirtualHostName() throws Exception - { - // Set up vhosts - getConfigXml().addProperty("virtualhosts.virtualhost.name", "dot.in.a.name"); - // Add a single property which is inside the <dot.in.a.name> virtual host tag - the message store - getConfigXml().addProperty("virtualhosts.virtualhost.dot..in..a..name.store.class", TestableMemoryMessageStore.class.getName()); - - VirtualHost test = createVirtualHost("dot.in.a.name"); - - // Check, that the property stored within the <dot.in.a.name> tag has been properly loaded - assertEquals("virtual host with dots in the name has been properly loaded", TestableMemoryMessageStore.class.getName(), test.getMessageStore().getClass().getName()); - } - - public void testStoreTransactionIdleTimeoutClose() throws Exception - { - VirtualHost vhost = createVirtualHost(getName()); - assertEquals("Unexpected StoreTransactionIdleTimeoutClose value", 0, vhost.getConfiguration().getTransactionTimeoutIdleClose()); - - when(_broker.getAttribute(Broker.VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE)).thenReturn(1000l); - assertEquals("Unexpected StoreTransactionIdleTimeoutClose value", 1000l, vhost.getConfiguration().getTransactionTimeoutIdleClose()); - - vhost.getConfiguration().getConfig().setProperty("transactionTimeout.idleClose", 2000l); - assertEquals("Unexpected StoreTransactionIdleTimeoutClose value", 2000l, vhost.getConfiguration().getTransactionTimeoutIdleClose()); - } - - public void testStoreTransactionIdleTimeoutWarn() throws Exception - { - VirtualHost vhost = createVirtualHost(getName()); - assertEquals("Unexpected StoreTransactionIdleTimeoutWarn value", 0, vhost.getConfiguration().getTransactionTimeoutIdleWarn()); - - when(_broker.getAttribute(Broker.VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_WARN)).thenReturn(1000l); - assertEquals("Unexpected StoreTransactionIdleTimeoutWarn value", 1000l, vhost.getConfiguration().getTransactionTimeoutIdleWarn()); - - vhost.getConfiguration().getConfig().setProperty("transactionTimeout.idleWarn", 2000l); - assertEquals("Unexpected StoreTransactionIdleTimeoutWarn value", 2000l, vhost.getConfiguration().getTransactionTimeoutIdleWarn()); - } - - public void testStoreTransactionOpenTimeoutClose() throws Exception - { - VirtualHost vhost = createVirtualHost(getName()); - assertEquals("Unexpected StoreTransactionOpenTimeoutClose value", 0, vhost.getConfiguration().getTransactionTimeoutOpenClose()); - - when(_broker.getAttribute(Broker.VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE)).thenReturn(1000l); - assertEquals("Unexpected StoreTransactionOpenTimeoutClose value", 1000l, vhost.getConfiguration().getTransactionTimeoutOpenClose()); - - vhost.getConfiguration().getConfig().setProperty("transactionTimeout.openClose", 2000l); - assertEquals("Unexpected StoreTransactionOpenTimeoutClose value", 2000l, vhost.getConfiguration().getTransactionTimeoutOpenClose()); - } - - public void testStoreTransactionOpenTimeoutWarn() throws Exception - { - VirtualHost vhost = createVirtualHost(getName()); - assertEquals("Unexpected StoreTransactionOpenTimeoutWarn value", 0, vhost.getConfiguration().getTransactionTimeoutOpenWarn()); - - when(_broker.getAttribute(Broker.VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_WARN)).thenReturn(1000l); - assertEquals("Unexpected StoreTransactionOpenTimeoutWarn value", 1000l, vhost.getConfiguration().getTransactionTimeoutOpenWarn()); - - vhost.getConfiguration().getConfig().setProperty("transactionTimeout.openWarn", 2000l); - assertEquals("Unexpected StoreTransactionOpenTimeoutWarn value", 2000l, vhost.getConfiguration().getTransactionTimeoutOpenWarn()); - } -} diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/plugins/AbstractConfigurationTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/plugins/AbstractConfigurationTest.java deleted file mode 100644 index 79abae85cd..0000000000 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/plugins/AbstractConfigurationTest.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * - * 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.configuration.plugins; - -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; - -import org.apache.log4j.Logger; -import org.apache.qpid.test.utils.QpidTestCase; - -import java.util.List; - -/** - * Test that verifies that given a Configuration a ConfigurationPlugin can - * process and validate that data. - */ -public class AbstractConfigurationTest extends QpidTestCase -{ - private static final Logger _logger = Logger.getLogger(AbstractConfigurationTest.class); - - private static final double DOUBLE = 3.14; - private static final long POSITIVE_LONG = 1000; - private static final long NEGATIVE_LONG = -1000; - private static final int LIST_SIZE = 3; - - class TestConfigPlugin extends AbstractConfiguration - { - @Override - public String[] getElementsProcessed() - { - return new String[]{"[@property]", "name", - "positiveLong", "negativeLong", - "true", "list", "double"}; - } - - @Override - public void validateConfiguration() throws ConfigurationException - { - // no validation required - } - - public String getName() - { - return getStringValue("name"); - } - - public String getProperty() - { - return getStringValue("[@property]"); - } - - - } - - private TestConfigPlugin _plugin; - - @Override - public void setUp() throws Exception - { - // Test does not directly use the AppRegistry but the configured broker - // is required for the correct ConfigurationPlugin processing - super.setUp(); - XMLConfiguration xmlConfig = new XMLConfiguration(); - xmlConfig.addProperty("base.element[@property]", "property"); - xmlConfig.addProperty("base.element.name", "name"); - // We make these strings as that is how they will be read from the file. - xmlConfig.addProperty("base.element.positiveLong", String.valueOf(POSITIVE_LONG)); - xmlConfig.addProperty("base.element.negativeLong", String.valueOf(NEGATIVE_LONG)); - xmlConfig.addProperty("base.element.boolean", String.valueOf(true)); - xmlConfig.addProperty("base.element.double", String.valueOf(DOUBLE)); - for (int i = 0; i < LIST_SIZE; i++) - { - xmlConfig.addProperty("base.element.list", i); - } - - //Use a composite configuration as this is what our broker code uses. - CompositeConfiguration composite = new CompositeConfiguration(); - composite.addConfiguration(xmlConfig); - - _plugin = new TestConfigPlugin(); - - try - { - _plugin.setConfiguration("base.element", composite.subset("base.element")); - } - catch (ConfigurationException e) - { - _logger.error("Error setting up plugin configuration", e); - fail(e.toString()); - } - - } - - public void testHasConfiguration() - { - assertTrue("Plugin has no configuration ", _plugin.hasConfiguration()); - _plugin = new TestConfigPlugin(); - assertFalse("Plugins has configuration", _plugin.hasConfiguration()); - } - - public void testValuesRetrieved() - { - assertEquals("Name not correct", "name", _plugin.getName()); - assertEquals("Property not correct", "property", _plugin.getProperty()); - } - - public void testContainsPositiveLong() - { - assertTrue("positiveLong is not positive", _plugin.containsPositiveLong("positiveLong")); - assertFalse("NonExistentValue was found", _plugin.containsPositiveLong("NonExistentValue")); - - try - { - _plugin.validatePositiveLong("positiveLong"); - } - catch (ConfigurationException e) - { - fail(e.getMessage()); - } - - try - { - _plugin.validatePositiveLong("negativeLong"); - fail("negativeLong should not be positive"); - } - catch (ConfigurationException e) - { - assertEquals("negativeLong should not be reported as positive", - "TestConfigPlugin: unable to configure invalid negativeLong:" + NEGATIVE_LONG, e.getMessage()); - } - - } - - public void testDouble() - { - assertEquals("Double value not returned", DOUBLE, _plugin.getDoubleValue("double")); - assertEquals("default Double value not returned", 0.0, _plugin.getDoubleValue("NonExistent")); - assertEquals("set default Double value not returned", DOUBLE, _plugin.getDoubleValue("NonExistent", DOUBLE)); - } - - public void testLong() - { - assertTrue("Long value not returned", _plugin.containsLong("positiveLong")); - assertFalse("Long value returned", _plugin.containsLong("NonExistent")); - assertEquals("Long value not returned", POSITIVE_LONG, _plugin.getLongValue("positiveLong")); - assertEquals("default Long value not returned", 0, _plugin.getLongValue("NonExistent")); - assertEquals("set default Long value not returned", NEGATIVE_LONG, _plugin.getLongValue("NonExistent", NEGATIVE_LONG)); - } - - public void testInt() - { - assertTrue("Int value not returned", _plugin.containsInt("positiveLong")); - assertFalse("Int value returned", _plugin.containsInt("NonExistent")); - assertEquals("Int value not returned", (int) POSITIVE_LONG, _plugin.getIntValue("positiveLong")); - assertEquals("default Int value not returned", 0, _plugin.getIntValue("NonExistent")); - assertEquals("set default Int value not returned", (int) NEGATIVE_LONG, _plugin.getIntValue("NonExistent", (int) NEGATIVE_LONG)); - } - - public void testString() - { - assertEquals("String value not returned", "name", _plugin.getStringValue("name")); - assertNull("Null default String value not returned", _plugin.getStringValue("NonExistent", null)); - assertNull("default String value not returned", _plugin.getStringValue("NonExistent")); - assertEquals("default String value not returned", "Default", _plugin.getStringValue("NonExistent", "Default")); - } - - public void testBoolean() - { - assertTrue("Boolean value not returned", _plugin.containsBoolean("boolean")); - assertFalse("Boolean value not returned", _plugin.containsBoolean("NonExistent")); - assertTrue("Boolean value not returned", _plugin.getBooleanValue("boolean")); - assertFalse("default String value not returned", _plugin.getBooleanValue("NonExistent")); - assertTrue("set default String value not returned", _plugin.getBooleanValue("NonExistent", true)); - } - - public void testList() - { - assertTrue("list not found in plugin", _plugin.contains("list")); - List list = _plugin.getListValue("list"); - assertNotNull("Returned list should not be null", list); - assertEquals("List should not be empty", LIST_SIZE, list.size()); - - list = _plugin.getListValue("NonExistent"); - assertNotNull("Returned list should not be null", list); - assertEquals("List is not empty", 0, list.size()); - } - - public void testContains() - { - assertTrue("list not found in plugin", _plugin.contains("list")); - assertFalse("NonExistent found in plugin", _plugin.contains("NonExistent")); - } - -} diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/StoreUpgraderTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/StoreUpgraderTest.java new file mode 100644 index 0000000000..cc5137ed66 --- /dev/null +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/StoreUpgraderTest.java @@ -0,0 +1,415 @@ +/* + * + * 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.configuration.startup; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import junit.framework.TestCase; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfigurationEntryStore; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.VirtualHost; + +public class StoreUpgraderTest extends TestCase +{ + + private final UUID _brokerId = UUID.randomUUID(); + private final UUID _virtualHostId = UUID.randomUUID(); + private ConfigurationEntryStore _store = mock(ConfigurationEntryStore.class); + + public void testUpgrade13To14_RejectsConfigPath() throws Exception + { + HashMap<String, Object> virtualHostAttributes = new HashMap<String, Object>(); + virtualHostAttributes.put("name", "test"); + virtualHostAttributes.put("type", "STANDARD"); + virtualHostAttributes.put("configPath", "/mypath"); + try + { + doTest(_store, virtualHostAttributes); + fail("Upgrade of virtual host with configuration XML is unsupported at the moment"); + } + catch(IllegalConfigurationException e) + { + // pass + } + } + + public void testUpgrade13To14_Derby() throws Exception + { + HashMap<String, Object> virtualHostAttributes = new HashMap<String, Object>(); + virtualHostAttributes.put("name", "test"); + virtualHostAttributes.put("type", "STANDARD"); + virtualHostAttributes.put("storeType", "DERBy"); + virtualHostAttributes.put("storePath", "/mystorepath"); + virtualHostAttributes.put("storeUnderfullSize", 1000); + virtualHostAttributes.put("storeOverfullSize", 2000); + + doTest(_store, virtualHostAttributes); + + ConfigurationEntry expectNewRoot = new ConfigurationEntry(_brokerId, Broker.class.getSimpleName(), Collections.<String, Object>singletonMap(Broker.MODEL_VERSION, "1.4"), Collections.singleton(_virtualHostId), _store); + ConfigurationEntry expectedNewVirtualHost; + { + Map<String, Object> expectedNewVirtualHostMessageSettings = new HashMap<String, Object>(); + expectedNewVirtualHostMessageSettings.put("storeType", "DERBY"); + expectedNewVirtualHostMessageSettings.put("storePath", "/mystorepath"); + expectedNewVirtualHostMessageSettings.put("storeUnderfullSize", 1000); + expectedNewVirtualHostMessageSettings.put("storeOverfullSize", 2000); + + Map<String, Object> expectedNewVirtualHostAttributes = new HashMap<String, Object>(); + expectedNewVirtualHostAttributes.put(VirtualHost.NAME, "test"); + expectedNewVirtualHostAttributes.put(VirtualHost.TYPE, "STANDARD"); + expectedNewVirtualHostAttributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, expectedNewVirtualHostMessageSettings); + + expectedNewVirtualHost = new ConfigurationEntry(_virtualHostId, VirtualHost.class.getSimpleName(), expectedNewVirtualHostAttributes, Collections.<UUID>emptySet(), _store); + } + verify(_store).save(expectedNewVirtualHost, expectNewRoot); + } + + public void testUpgrade13To14_DerbyConfigurationStore() throws Exception + { + HashMap<String, Object> virtualHostAttributes = new HashMap<String, Object>(); + virtualHostAttributes.put("name", "test"); + virtualHostAttributes.put("type", "STANDARD"); + virtualHostAttributes.put("configStoreType", "DERBy"); + virtualHostAttributes.put("configStorePath", "/mystorepath"); + + doTest(_store, virtualHostAttributes); + + ConfigurationEntry expectNewRoot = new ConfigurationEntry(_brokerId, Broker.class.getSimpleName(), Collections.<String, Object>singletonMap(Broker.MODEL_VERSION, "1.4"), Collections.singleton(_virtualHostId), _store); + ConfigurationEntry expectedNewVirtualHost; + { + Map<String, Object> expectedNewVirtualHostConfigurationStoreSettings = new HashMap<String, Object>(); + expectedNewVirtualHostConfigurationStoreSettings.put("storeType", "DERBY"); + expectedNewVirtualHostConfigurationStoreSettings.put("storePath", "/mystorepath"); + + Map<String, Object> expectedNewVirtualHostAttributes = new HashMap<String, Object>(); + expectedNewVirtualHostAttributes.put(VirtualHost.NAME, "test"); + expectedNewVirtualHostAttributes.put(VirtualHost.TYPE, "STANDARD"); + expectedNewVirtualHostAttributes.put(VirtualHost.CONFIGURATION_STORE_SETTINGS, expectedNewVirtualHostConfigurationStoreSettings); + + expectedNewVirtualHost = new ConfigurationEntry(_virtualHostId, VirtualHost.class.getSimpleName(), expectedNewVirtualHostAttributes, Collections.<UUID>emptySet(), _store); + } + verify(_store).save(expectedNewVirtualHost, expectNewRoot); + } + + public void testUpgrade13To14_JsonConfigurationStore() throws Exception + { + HashMap<String, Object> virtualHostAttributes = new HashMap<String, Object>(); + virtualHostAttributes.put("name", "test"); + virtualHostAttributes.put("type", "STANDARD"); + virtualHostAttributes.put("configStoreType", "JsoN"); + virtualHostAttributes.put("configStorePath", "/mystorepath"); + + doTest(_store, virtualHostAttributes); + + ConfigurationEntry expectNewRoot = new ConfigurationEntry(_brokerId, Broker.class.getSimpleName(), Collections.<String, Object>singletonMap(Broker.MODEL_VERSION, "1.4"), Collections.singleton(_virtualHostId), _store); + ConfigurationEntry expectedNewVirtualHost; + { + Map<String, Object> expectedNewVirtualHostConfigurationStoreSettings = new HashMap<String, Object>(); + expectedNewVirtualHostConfigurationStoreSettings.put("storeType", "JSON"); + expectedNewVirtualHostConfigurationStoreSettings.put("storePath", "/mystorepath"); + + Map<String, Object> expectedNewVirtualHostAttributes = new HashMap<String, Object>(); + expectedNewVirtualHostAttributes.put(VirtualHost.NAME, "test"); + expectedNewVirtualHostAttributes.put(VirtualHost.TYPE, "STANDARD"); + expectedNewVirtualHostAttributes.put(VirtualHost.CONFIGURATION_STORE_SETTINGS, expectedNewVirtualHostConfigurationStoreSettings); + + expectedNewVirtualHost = new ConfigurationEntry(_virtualHostId, VirtualHost.class.getSimpleName(), expectedNewVirtualHostAttributes, Collections.<UUID>emptySet(), _store); + } + verify(_store).save(expectedNewVirtualHost, expectNewRoot); + } + + public void testUpgrade13To14_BdbHa() throws Exception + { + HashMap<String, Object> virtualHostAttributes = new HashMap<String, Object>(); + virtualHostAttributes.put("name", "test"); + virtualHostAttributes.put("type", "BDB_HA"); + virtualHostAttributes.put("storeType", "BdB-HA"); + virtualHostAttributes.put("storePath", "/mystorepath"); + virtualHostAttributes.put("storeUnderfullSize", 1000); + virtualHostAttributes.put("storeOverfullSize", 2000); + virtualHostAttributes.put("haNodeName", "node1"); + virtualHostAttributes.put("haGroupName", "group1"); + virtualHostAttributes.put("haHelperAddress", "helper:1000"); + virtualHostAttributes.put("haCoalescingSync", true); + virtualHostAttributes.put("haNodeAddress", "nodeaddr:1000"); + virtualHostAttributes.put("haDurability", "sync,sync,all"); + virtualHostAttributes.put("haDesignatedPrimary", true); + virtualHostAttributes.put("haReplicationConfig", Collections.singletonMap("hasettings", "havalue")); + virtualHostAttributes.put("bdbEnvironmentConfig", Collections.singletonMap("envsettings", "envvalue")); + + doTest(_store, virtualHostAttributes); + + ConfigurationEntry expectNewRoot = new ConfigurationEntry(_brokerId, Broker.class.getSimpleName(), Collections.<String, Object>singletonMap(Broker.MODEL_VERSION, "1.4"), Collections.singleton(_virtualHostId), _store); + ConfigurationEntry expectedNewVirtualHost; + { + Map<String, Object> expectedNewVirtualHostMessageSettings = new HashMap<String, Object>(); + expectedNewVirtualHostMessageSettings.put("storePath", "/mystorepath"); + expectedNewVirtualHostMessageSettings.put("storeUnderfullSize", 1000); + expectedNewVirtualHostMessageSettings.put("storeOverfullSize", 2000); + expectedNewVirtualHostMessageSettings.put("haNodeName", "node1"); + expectedNewVirtualHostMessageSettings.put("haGroupName", "group1"); + expectedNewVirtualHostMessageSettings.put("haHelperAddress", "helper:1000"); + expectedNewVirtualHostMessageSettings.put("haCoalescingSync", true); + expectedNewVirtualHostMessageSettings.put("haNodeAddress", "nodeaddr:1000"); + expectedNewVirtualHostMessageSettings.put("haDurability", "sync,sync,all"); + expectedNewVirtualHostMessageSettings.put("haDesignatedPrimary", true); + expectedNewVirtualHostMessageSettings.put("haReplicationConfig", Collections.singletonMap("hasettings", "havalue")); + expectedNewVirtualHostMessageSettings.put("bdbEnvironmentConfig", Collections.singletonMap("envsettings", "envvalue")); + + Map<String, Object> expectedNewVirtualHostAttributes = new HashMap<String, Object>(); + expectedNewVirtualHostAttributes.put(VirtualHost.NAME, "test"); + expectedNewVirtualHostAttributes.put(VirtualHost.TYPE, "BDB_HA"); + expectedNewVirtualHostAttributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, expectedNewVirtualHostMessageSettings); + + expectedNewVirtualHost = new ConfigurationEntry(_virtualHostId, VirtualHost.class.getSimpleName(), expectedNewVirtualHostAttributes, Collections.<UUID>emptySet(), _store); + } + verify(_store).save(expectedNewVirtualHost, expectNewRoot); + } + + public void testUpgrade13To14_Bdb() throws Exception + { + HashMap<String, Object> virtualHostAttributes = new HashMap<String, Object>(); + virtualHostAttributes.put("name", "test"); + virtualHostAttributes.put("type", "STANDARD"); + virtualHostAttributes.put("storeType", "BdB"); + virtualHostAttributes.put("storePath", "/mystorepath"); + virtualHostAttributes.put("storeUnderfullSize", 1000); + virtualHostAttributes.put("storeOverfullSize", 2000); + virtualHostAttributes.put("bdbEnvironmentConfig", Collections.singletonMap("envsettings", "envvalue")); + + doTest(_store, virtualHostAttributes); + + ConfigurationEntry expectNewRoot = new ConfigurationEntry(_brokerId, Broker.class.getSimpleName(), Collections.<String, Object>singletonMap(Broker.MODEL_VERSION, "1.4"), Collections.singleton(_virtualHostId), _store); + ConfigurationEntry expectedNewVirtualHost; + { + Map<String, Object> expectedNewVirtualHostMessageSettings = new HashMap<String, Object>(); + expectedNewVirtualHostMessageSettings.put("storeType", "BDB"); + expectedNewVirtualHostMessageSettings.put("storePath", "/mystorepath"); + expectedNewVirtualHostMessageSettings.put("storeUnderfullSize", 1000); + expectedNewVirtualHostMessageSettings.put("storeOverfullSize", 2000); + expectedNewVirtualHostMessageSettings.put("bdbEnvironmentConfig", Collections.singletonMap("envsettings", "envvalue")); + + Map<String, Object> expectedNewVirtualHostAttributes = new HashMap<String, Object>(); + expectedNewVirtualHostAttributes.put(VirtualHost.NAME, "test"); + expectedNewVirtualHostAttributes.put(VirtualHost.TYPE, "STANDARD"); + expectedNewVirtualHostAttributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, expectedNewVirtualHostMessageSettings); + + expectedNewVirtualHost = new ConfigurationEntry(_virtualHostId, VirtualHost.class.getSimpleName(), expectedNewVirtualHostAttributes, Collections.<UUID>emptySet(), _store); + } + verify(_store).save(expectedNewVirtualHost, expectNewRoot); + } + + public void testUpgrade13To14_BdbMessageStoreAndConfigurationStore() throws Exception + { + HashMap<String, Object> virtualHostAttributes = new HashMap<String, Object>(); + virtualHostAttributes.put("name", "test"); + virtualHostAttributes.put("type", "STANDARD"); + virtualHostAttributes.put("storeType", "BdB"); + virtualHostAttributes.put("storePath", "/mystorepath"); + virtualHostAttributes.put("storeUnderfullSize", 1000); + virtualHostAttributes.put("storeOverfullSize", 2000); + virtualHostAttributes.put("bdbEnvironmentConfig", Collections.singletonMap("envsettings", "envvalue")); + virtualHostAttributes.put("configStoreType", "BdB"); + virtualHostAttributes.put("configStorePath", "/mystorepath2"); + + doTest(_store, virtualHostAttributes); + + ConfigurationEntry expectNewRoot = new ConfigurationEntry(_brokerId, Broker.class.getSimpleName(), Collections.<String, Object>singletonMap(Broker.MODEL_VERSION, "1.4"), Collections.singleton(_virtualHostId), _store); + ConfigurationEntry expectedNewVirtualHost; + { + Map<String, Object> expectedNewVirtualHostMessageSettings = new HashMap<String, Object>(); + expectedNewVirtualHostMessageSettings.put("storeType", "BDB"); + expectedNewVirtualHostMessageSettings.put("storePath", "/mystorepath"); + expectedNewVirtualHostMessageSettings.put("storeUnderfullSize", 1000); + expectedNewVirtualHostMessageSettings.put("storeOverfullSize", 2000); + expectedNewVirtualHostMessageSettings.put("bdbEnvironmentConfig", Collections.singletonMap("envsettings", "envvalue")); + + Map<String, Object> expectedNewVirtualHostConfigurationSettings = new HashMap<String, Object>(); + expectedNewVirtualHostConfigurationSettings.put("storeType", "BDB"); + expectedNewVirtualHostConfigurationSettings.put("storePath", "/mystorepath2"); + expectedNewVirtualHostConfigurationSettings.put("bdbEnvironmentConfig", Collections.singletonMap("envsettings", "envvalue")); + + Map<String, Object> expectedNewVirtualHostAttributes = new HashMap<String, Object>(); + expectedNewVirtualHostAttributes.put(VirtualHost.NAME, "test"); + expectedNewVirtualHostAttributes.put(VirtualHost.TYPE, "STANDARD"); + expectedNewVirtualHostAttributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, expectedNewVirtualHostMessageSettings); + expectedNewVirtualHostAttributes.put(VirtualHost.CONFIGURATION_STORE_SETTINGS, expectedNewVirtualHostConfigurationSettings); + + expectedNewVirtualHost = new ConfigurationEntry(_virtualHostId, VirtualHost.class.getSimpleName(), expectedNewVirtualHostAttributes, Collections.<UUID>emptySet(), _store); + } + verify(_store).save(expectedNewVirtualHost, expectNewRoot); + } + + public void testUpgrade13To14_JDBC() throws Exception + { + HashMap<String, Object> virtualHostAttributes = new HashMap<String, Object>(); + virtualHostAttributes.put("name", "test"); + virtualHostAttributes.put("type", "STANDARD"); + virtualHostAttributes.put("storeType", "JdBC"); + virtualHostAttributes.put("connectionURL", "jdbc:test"); + virtualHostAttributes.put("connectionPool", "BONECP"); + virtualHostAttributes.put("jdbcBigIntType", "NUMBER"); + virtualHostAttributes.put("jdbcBytesForBlob", true); + virtualHostAttributes.put("jdbcVarbinaryType", "TEST"); + virtualHostAttributes.put("jdbcBlobType", "BLOB"); + virtualHostAttributes.put("partitionCount", 10); + virtualHostAttributes.put("maxConnectionsPerPartition", 8); + virtualHostAttributes.put("minConnectionsPerPartition", 2); + + doTest(_store, virtualHostAttributes); + + ConfigurationEntry expectNewRoot = new ConfigurationEntry(_brokerId, Broker.class.getSimpleName(), Collections.<String, Object>singletonMap(Broker.MODEL_VERSION, "1.4"), Collections.singleton(_virtualHostId), _store); + ConfigurationEntry expectedNewVirtualHost; + { + Map<String, Object> expectedNewVirtualHostMessageSettings = new HashMap<String, Object>(); + expectedNewVirtualHostMessageSettings.put("storeType", "JDBC"); + expectedNewVirtualHostMessageSettings.put("connectionURL", "jdbc:test"); + expectedNewVirtualHostMessageSettings.put("connectionPool", "BONECP"); + expectedNewVirtualHostMessageSettings.put("jdbcBigIntType", "NUMBER"); + expectedNewVirtualHostMessageSettings.put("jdbcBytesForBlob", true); + expectedNewVirtualHostMessageSettings.put("jdbcVarbinaryType", "TEST"); + expectedNewVirtualHostMessageSettings.put("jdbcBlobType", "BLOB"); + expectedNewVirtualHostMessageSettings.put("partitionCount", 10); + expectedNewVirtualHostMessageSettings.put("maxConnectionsPerPartition", 8); + expectedNewVirtualHostMessageSettings.put("minConnectionsPerPartition", 2); + + Map<String, Object> expectedNewVirtualHostAttributes = new HashMap<String, Object>(); + expectedNewVirtualHostAttributes.put(VirtualHost.NAME, "test"); + expectedNewVirtualHostAttributes.put(VirtualHost.TYPE, "STANDARD"); + expectedNewVirtualHostAttributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, expectedNewVirtualHostMessageSettings); + + expectedNewVirtualHost = new ConfigurationEntry(_virtualHostId, VirtualHost.class.getSimpleName(), expectedNewVirtualHostAttributes, Collections.<UUID>emptySet(), _store); + } + verify(_store).save(expectedNewVirtualHost, expectNewRoot); + } + + public void testUpgrade13To14_JDBC_withStorePath() throws Exception + { + HashMap<String, Object> virtualHostAttributes = new HashMap<String, Object>(); + virtualHostAttributes.put("name", "test"); + virtualHostAttributes.put("type", "STANDARD"); + virtualHostAttributes.put("storeType", "JdBC"); + virtualHostAttributes.put("storePath", "jdbc:test"); + + doTest(_store, virtualHostAttributes); + + ConfigurationEntry expectNewRoot = new ConfigurationEntry(_brokerId, Broker.class.getSimpleName(), Collections.<String, Object>singletonMap(Broker.MODEL_VERSION, "1.4"), Collections.singleton(_virtualHostId), _store); + ConfigurationEntry expectedNewVirtualHost; + { + Map<String, Object> expectedNewVirtualHostMessageSettings = new HashMap<String, Object>(); + expectedNewVirtualHostMessageSettings.put("storeType", "JDBC"); + expectedNewVirtualHostMessageSettings.put("connectionURL", "jdbc:test"); + + Map<String, Object> expectedNewVirtualHostAttributes = new HashMap<String, Object>(); + expectedNewVirtualHostAttributes.put(VirtualHost.NAME, "test"); + expectedNewVirtualHostAttributes.put(VirtualHost.TYPE, "STANDARD"); + expectedNewVirtualHostAttributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, expectedNewVirtualHostMessageSettings); + + expectedNewVirtualHost = new ConfigurationEntry(_virtualHostId, VirtualHost.class.getSimpleName(), expectedNewVirtualHostAttributes, Collections.<UUID>emptySet(), _store); + } + verify(_store).save(expectedNewVirtualHost, expectNewRoot); + } + + public void testUpgrade13To14_JDBCConfigurationStoreAndMessageStore() throws Exception + { + HashMap<String, Object> virtualHostAttributes = new HashMap<String, Object>(); + virtualHostAttributes.put("name", "test"); + virtualHostAttributes.put("type", "STANDARD"); + virtualHostAttributes.put("storeType", "JdBC"); + virtualHostAttributes.put("connectionURL", "jdbc:test"); + virtualHostAttributes.put("connectionPool", "BONECP"); + virtualHostAttributes.put("jdbcBigIntType", "NUMBER"); + virtualHostAttributes.put("jdbcBytesForBlob", true); + virtualHostAttributes.put("jdbcVarbinaryType", "TEST"); + virtualHostAttributes.put("jdbcBlobType", "BLOB"); + virtualHostAttributes.put("partitionCount", 10); + virtualHostAttributes.put("maxConnectionsPerPartition", 8); + virtualHostAttributes.put("minConnectionsPerPartition", 2); + virtualHostAttributes.put("configStoreType", "JdBC"); + virtualHostAttributes.put("configConnectionURL", "jdbc:test2"); + + doTest(_store, virtualHostAttributes); + + ConfigurationEntry expectNewRoot = new ConfigurationEntry(_brokerId, Broker.class.getSimpleName(), Collections.<String, Object>singletonMap(Broker.MODEL_VERSION, "1.4"), Collections.singleton(_virtualHostId), _store); + ConfigurationEntry expectedNewVirtualHost; + { + Map<String, Object> expectedNewVirtualHostMessageSettings = new HashMap<String, Object>(); + expectedNewVirtualHostMessageSettings.put("storeType", "JDBC"); + expectedNewVirtualHostMessageSettings.put("connectionURL", "jdbc:test"); + expectedNewVirtualHostMessageSettings.put("connectionPool", "BONECP"); + expectedNewVirtualHostMessageSettings.put("jdbcBigIntType", "NUMBER"); + expectedNewVirtualHostMessageSettings.put("jdbcBytesForBlob", true); + expectedNewVirtualHostMessageSettings.put("jdbcVarbinaryType", "TEST"); + expectedNewVirtualHostMessageSettings.put("jdbcBlobType", "BLOB"); + expectedNewVirtualHostMessageSettings.put("partitionCount", 10); + expectedNewVirtualHostMessageSettings.put("maxConnectionsPerPartition", 8); + expectedNewVirtualHostMessageSettings.put("minConnectionsPerPartition", 2); + + Map<String, Object> expectedNewVirtualHostConfigurationSettings = new HashMap<String, Object>(); + expectedNewVirtualHostConfigurationSettings.put("storeType", "JDBC"); + expectedNewVirtualHostConfigurationSettings.put("connectionURL", "jdbc:test2"); + expectedNewVirtualHostConfigurationSettings.put("connectionPool", "BONECP"); + expectedNewVirtualHostConfigurationSettings.put("jdbcBigIntType", "NUMBER"); + expectedNewVirtualHostConfigurationSettings.put("jdbcBytesForBlob", true); + expectedNewVirtualHostConfigurationSettings.put("jdbcVarbinaryType", "TEST"); + expectedNewVirtualHostConfigurationSettings.put("jdbcBlobType", "BLOB"); + expectedNewVirtualHostConfigurationSettings.put("partitionCount", 10); + expectedNewVirtualHostConfigurationSettings.put("maxConnectionsPerPartition", 8); + expectedNewVirtualHostConfigurationSettings.put("minConnectionsPerPartition", 2); + + Map<String, Object> expectedNewVirtualHostAttributes = new HashMap<String, Object>(); + expectedNewVirtualHostAttributes.put(VirtualHost.NAME, "test"); + expectedNewVirtualHostAttributes.put(VirtualHost.TYPE, "STANDARD"); + expectedNewVirtualHostAttributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, expectedNewVirtualHostMessageSettings); + expectedNewVirtualHostAttributes.put(VirtualHost.CONFIGURATION_STORE_SETTINGS, expectedNewVirtualHostConfigurationSettings); + + expectedNewVirtualHost = new ConfigurationEntry(_virtualHostId, VirtualHost.class.getSimpleName(), expectedNewVirtualHostAttributes, Collections.<UUID>emptySet(), _store); + } + verify(_store).save(expectedNewVirtualHost, expectNewRoot); + } + + private void doTest(ConfigurationEntryStore store, Map<String,Object> virtualHostAttributes) + { + final ConfigurationEntry virtualHostEntry = new ConfigurationEntry(_virtualHostId, VirtualHost.class.getSimpleName(), virtualHostAttributes, Collections.<UUID>emptySet(), store); + + final ConfigurationEntry rootEntry; + { + Map<String, Object> rootEntryAttributes = Collections.<String, Object>singletonMap(Broker.MODEL_VERSION, "1.3"); + rootEntry = new ConfigurationEntry(_brokerId, Broker.class.getSimpleName(), rootEntryAttributes, Collections.singleton(_virtualHostId), store); + } + + when(store.getRootEntry()).thenReturn(rootEntry); + when(store.getEntry(_virtualHostId)).thenReturn(virtualHostEntry); + + StoreUpgrader.UPGRADE_1_3.doUpgrade(store); + } + +} diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostRecovererTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostRecovererTest.java index 9649838b00..0eea2663fd 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostRecovererTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostRecovererTest.java @@ -23,7 +23,7 @@ package org.apache.qpid.server.configuration.startup; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import java.io.File; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -35,34 +35,13 @@ import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.stats.StatisticsGatherer; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.TestMemoryMessageStore; +import org.apache.qpid.server.store.TestableMemoryMessageStore; import org.apache.qpid.server.virtualhost.StandardVirtualHostFactory; -import org.apache.qpid.test.utils.TestFileUtils; public class VirtualHostRecovererTest extends TestCase { - public void testCreate() - { - StatisticsGatherer statisticsGatherer = mock(StatisticsGatherer.class); - SecurityManager securityManager = mock(SecurityManager.class); - ConfigurationEntry entry = mock(ConfigurationEntry.class); - Broker parent = mock(Broker.class); - when(parent.getAttribute(Broker.VIRTUALHOST_HOUSEKEEPING_CHECK_PERIOD)).thenReturn(3000l); - when(parent.getSecurityManager()).thenReturn(securityManager); - - VirtualHostRecoverer recoverer = new VirtualHostRecoverer(statisticsGatherer); - Map<String, Object> attributes = new HashMap<String, Object>(); - String name = getName(); - attributes.put(VirtualHost.NAME, name); - File file = TestFileUtils.createTempFile(this, ".xml", "<virtualhosts><virtualhost><name>" + name + "</name><" + name - + "></" + name + "></virtualhost></virtualhosts>"); - attributes.put(VirtualHost.CONFIG_PATH, file.getAbsolutePath()); - when(entry.getAttributes()).thenReturn(attributes); - - VirtualHost host = recoverer.create(null, entry, parent); - - assertNotNull("Null is returned", host); - assertEquals("Unexpected name", getName(), host.getName()); - } public void testCreateVirtualHostFromStoreConfigAttributes() { @@ -77,8 +56,7 @@ public class VirtualHostRecovererTest extends TestCase Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(VirtualHost.NAME, getName()); attributes.put(VirtualHost.TYPE, StandardVirtualHostFactory.TYPE); - - attributes.put(VirtualHost.STORE_TYPE, "TESTMEMORY"); + attributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, Collections.singletonMap(MessageStore.STORE_TYPE, TestMemoryMessageStore.TYPE)); when(entry.getAttributes()).thenReturn(attributes); VirtualHost host = recoverer.create(null, entry, parent); @@ -91,15 +69,9 @@ public class VirtualHostRecovererTest extends TestCase { Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(VirtualHost.NAME, getName()); - attributes.put(VirtualHost.CONFIG_PATH, "/path/to/virtualhost.xml"); - String[] mandatoryAttributes = {VirtualHost.NAME, VirtualHost.CONFIG_PATH}; - - checkMandatoryAttributesAreValidated(mandatoryAttributes, attributes); - - attributes = new HashMap<String, Object>(); - attributes.put(VirtualHost.NAME, getName()); - attributes.put(VirtualHost.STORE_TYPE, "MEMORY"); - mandatoryAttributes = new String[]{VirtualHost.NAME, VirtualHost.STORE_TYPE}; + attributes.put(VirtualHost.TYPE, StandardVirtualHostFactory.TYPE); + attributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, Collections.singletonMap(MessageStore.STORE_TYPE, TestMemoryMessageStore.TYPE)); + String[] mandatoryAttributes = {VirtualHost.NAME, VirtualHost.TYPE, VirtualHost.MESSAGE_STORE_SETTINGS}; checkMandatoryAttributesAreValidated(mandatoryAttributes, attributes); } diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java index 133eb94e43..fdf3ec24a1 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java @@ -79,7 +79,7 @@ public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase _virtualHostId = UUID.randomUUID(); _virtualHostAttributes = new HashMap<String, Object>(); _virtualHostAttributes.put(VirtualHost.NAME, "test"); - _virtualHostAttributes.put(VirtualHost.CONFIG_PATH, "/path/to/phantom/test"); + _virtualHostAttributes.put(VirtualHost.TYPE, "STANDARD"); _authenticationProviderId = UUID.randomUUID(); _authenticationProviderAttributes = new HashMap<String, Object>(); @@ -135,7 +135,7 @@ public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase { Map<String, Object> virtualHostAttributes = new HashMap<String, Object>(); virtualHostAttributes.put(VirtualHost.NAME, getName()); - virtualHostAttributes.put(VirtualHost.CONFIG_PATH, "/path/to/phantom/virtualhost/config"); + virtualHostAttributes.put(VirtualHost.TYPE, "STANDARD"); UUID virtualHostId = UUID.randomUUID(); addConfiguration(virtualHostId, VirtualHost.class.getSimpleName(), virtualHostAttributes); @@ -149,13 +149,13 @@ public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase { Map<String, Object> virtualHost1Attributes = new HashMap<String, Object>(); virtualHost1Attributes.put(VirtualHost.NAME, "test1"); - virtualHost1Attributes.put(VirtualHost.CONFIG_PATH, "/path/to/phantom/virtualhost/config1"); + virtualHost1Attributes.put(VirtualHost.TYPE, "STANDARD"); UUID virtualHost1Id = UUID.randomUUID(); addConfiguration(virtualHost1Id, VirtualHost.class.getSimpleName(), virtualHost1Attributes); Map<String, Object> virtualHost2Attributes = new HashMap<String, Object>(); virtualHost2Attributes.put(VirtualHost.NAME, "test1"); - virtualHost2Attributes.put(VirtualHost.CONFIG_PATH, "/path/to/phantom/virtualhost/config2"); + virtualHost2Attributes.put(VirtualHost.TYPE, "STANDARD"); UUID virtualHost2Id = UUID.randomUUID(); addConfiguration(virtualHost2Id, VirtualHost.class.getSimpleName(), virtualHost2Attributes); @@ -207,7 +207,7 @@ public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase { Map<String, Object> virtualHostAttributes = new HashMap<String, Object>(); virtualHostAttributes.put(VirtualHost.NAME, "test1"); - virtualHostAttributes.put(VirtualHost.CONFIG_PATH, "/path/to/phantom/virtualhost/config1"); + virtualHostAttributes.put(VirtualHost.TYPE, "STANDARD"); UUID virtualHostId = UUID.randomUUID(); ConfigurationEntry hostEntry = new ConfigurationEntry(virtualHostId, VirtualHost.class.getSimpleName(), virtualHostAttributes, Collections.<UUID> emptySet(), _store); @@ -228,7 +228,7 @@ public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase Map<String, Object> virtualHostAttributes = new HashMap<String, Object>(); virtualHostAttributes.put(VirtualHost.NAME, "test"); - virtualHostAttributes.put(VirtualHost.CONFIG_PATH, "/path/to/new/phantom/test/configuration"); + virtualHostAttributes.put(VirtualHost.TYPE, "STANDARD"); ConfigurationEntry updatedEntry = new ConfigurationEntry(_virtualHostId, VirtualHost.class.getSimpleName(), virtualHostAttributes, hostEntry.getChildrenIds(), _store); @@ -372,7 +372,7 @@ public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase UUID virtualHostId = UUID.randomUUID(); Map<String, Object> virtualHostAttributes = new HashMap<String, Object>(); virtualHostAttributes.put(VirtualHost.NAME, "test1"); - virtualHostAttributes.put(VirtualHost.CONFIG_PATH, "/path/to/phantom/virtualhost/config1"); + virtualHostAttributes.put(VirtualHost.TYPE, "STANDARD"); ConfigurationEntry hostEntry = new ConfigurationEntry(virtualHostId, VirtualHost.class.getSimpleName(), virtualHostAttributes, Collections.<UUID> emptySet(), _store); diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java index 34b4fbf1ab..bcdfce1d0a 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java @@ -213,7 +213,7 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase when(virtualHost.getId()).thenReturn(virtualHostId); when(virtualHost.getType()).thenReturn(VirtualHost.class.getSimpleName()); Map<String, Object> attributes = new HashMap<String, Object>(); - attributes.put(VirtualHost.CONFIG_PATH, "/path/to/host.xml"); + attributes.put(VirtualHost.TYPE, "STANDARD"); when(virtualHost.getAttributes()).thenReturn(attributes); when(_store.getEntry(virtualHostId)).thenReturn(virtualHost); when(_root.getChildrenIds()).thenReturn(new HashSet<UUID>(Arrays.asList(_portEntryId, virtualHostId))); diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/messages/AbstractTestMessages.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/messages/AbstractTestMessages.java index db52bb0e29..d0a282c20f 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/messages/AbstractTestMessages.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/messages/AbstractTestMessages.java @@ -20,9 +20,6 @@ */ package org.apache.qpid.server.logging.messages; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.PropertiesConfiguration; - import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.logging.LogMessage; import org.apache.qpid.server.logging.LogSubject; @@ -35,7 +32,6 @@ import java.util.List; public abstract class AbstractTestMessages extends QpidTestCase { - protected Configuration _config = new PropertiesConfiguration(); protected LogMessage _logMessage = null; protected UnitTestMessageLogger _logger; protected LogSubject _logSubject = new TestBlankSubject(); diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java index b8ecc4a2c0..266049e611 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java @@ -33,6 +33,7 @@ import org.apache.qpid.server.configuration.RecovererProvider; import org.apache.qpid.server.configuration.startup.VirtualHostRecoverer; import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.stats.StatisticsGatherer; +import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.TestMemoryMessageStore; import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.StandardVirtualHostFactory; @@ -54,6 +55,15 @@ public class VirtualHostTest extends QpidTestCase TaskExecutor taskExecutor = mock(TaskExecutor.class); when(taskExecutor.isTaskExecutorThread()).thenReturn(true); when(_broker.getTaskExecutor()).thenReturn(taskExecutor); + when(_broker.getAttribute(Broker.QUEUE_ALERT_THRESHOLD_MESSAGE_AGE)).thenReturn(0l); + when(_broker.getAttribute(Broker.QUEUE_ALERT_THRESHOLD_MESSAGE_SIZE)).thenReturn(0l); + when(_broker.getAttribute(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_BYTES)).thenReturn(0l); + when(_broker.getAttribute(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES)).thenReturn(0l); + when(_broker.getAttribute(Broker.QUEUE_ALERT_REPEAT_GAP)).thenReturn(10000l); + when(_broker.getAttribute(Broker.QUEUE_MAXIMUM_DELIVERY_ATTEMPTS)).thenReturn(0); + when(_broker.getAttribute(Broker.QUEUE_FLOW_CONTROL_RESUME_SIZE_BYTES)).thenReturn(0l); + when(_broker.getAttribute(Broker.QUEUE_FLOW_CONTROL_SIZE_BYTES)).thenReturn(0l); + when(_broker.getAttribute(Broker.QUEUE_DEAD_LETTER_QUEUE_ENABLED)).thenReturn(false); _recovererProvider = mock(RecovererProvider.class); _statisticsGatherer = mock(StatisticsGatherer.class); @@ -79,7 +89,7 @@ public class VirtualHostTest extends QpidTestCase Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(VirtualHost.NAME, getName()); attributes.put(VirtualHost.TYPE, StandardVirtualHostFactory.TYPE); - attributes.put(VirtualHost.STORE_TYPE, TestMemoryMessageStore.TYPE); + attributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, Collections.singletonMap(MessageStore.STORE_TYPE, TestMemoryMessageStore.TYPE)); attributes.put(VirtualHost.STATE, State.QUIESCED); VirtualHost host = createHost(attributes); @@ -140,7 +150,7 @@ public class VirtualHostTest extends QpidTestCase Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(VirtualHost.NAME, getName()); attributes.put(VirtualHost.TYPE, StandardVirtualHostFactory.TYPE); - attributes.put(VirtualHost.STORE_TYPE, TestMemoryMessageStore.TYPE); + attributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, Collections.singletonMap(MessageStore.STORE_TYPE, TestMemoryMessageStore.TYPE)); VirtualHost host = createHost(attributes); return host; diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java index 31a0b9d358..02921f987c 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java @@ -33,8 +33,6 @@ import java.util.UUID; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.server.configuration.BrokerProperties; -import org.apache.qpid.server.configuration.QueueConfiguration; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.exchange.DefaultExchangeFactory; import org.apache.qpid.server.exchange.ExchangeImpl; import org.apache.qpid.server.logging.EventLogger; @@ -56,7 +54,6 @@ public class AMQQueueFactoryTest extends QpidTestCase private VirtualHost _virtualHost; private AMQQueueFactory _queueFactory; private List<AMQQueue> _queues; - private QueueConfiguration _queueConfiguration; @Override public void setUp() throws Exception @@ -67,12 +64,8 @@ public class AMQQueueFactoryTest extends QpidTestCase _virtualHost = mock(VirtualHost.class); when(_virtualHost.getSecurityManager()).thenReturn(mock(SecurityManager.class)); - - VirtualHostConfiguration vhostConfig = mock(VirtualHostConfiguration.class); - when(_virtualHost.getConfiguration()).thenReturn(vhostConfig); when(_virtualHost.getEventLogger()).thenReturn(new EventLogger()); - _queueConfiguration = mock(QueueConfiguration.class); - when(vhostConfig.getQueueConfiguration(anyString())).thenReturn(_queueConfiguration); + DurableConfigurationStore store = mock(DurableConfigurationStore.class); when(_virtualHost.getDurableConfigurationStore()).thenReturn(store); @@ -284,15 +277,14 @@ public class AMQQueueFactoryTest extends QpidTestCase String dlExchangeName = queueName + DefaultExchangeFactory.DEFAULT_DLE_NAME_SUFFIX; String dlQueueName = queueName + AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX; - when(_queueConfiguration.getMaxDeliveryCount()).thenReturn(5); - when(_queueConfiguration.isDeadLetterQueueEnabled()).thenReturn(true); - assertNull("The DLQ should not yet exist", _virtualHost.getQueue(dlQueueName)); assertNull("The alternate exchange should not yet exist", _virtualHost.getExchange(dlExchangeName)); Map<String,Object> attributes = new HashMap<String, Object>(); attributes.put(Queue.ID, UUID.randomUUID()); attributes.put(Queue.NAME, queueName); + attributes.put(Queue.CREATE_DLQ_ON_CREATION, true); + attributes.put(Queue.MAXIMUM_DELIVERY_ATTEMPTS, 5); AMQQueue queue = _queueFactory.createQueue(attributes); @@ -501,19 +493,16 @@ public class AMQQueueFactoryTest extends QpidTestCase } } - public void testMessageGroupFromConfig() throws Exception + public void testMessageGroupQueue() throws Exception { - Map<String,String> arguments = new HashMap<String, String>(); - - arguments.put(QueueArgumentsConverter.QPID_GROUP_HEADER_KEY,"mykey"); - arguments.put(QueueArgumentsConverter.QPID_SHARED_MSG_GROUP,"1"); - - QueueConfiguration qConf = mock(QueueConfiguration.class); - when(qConf.getArguments()).thenReturn(arguments); - when(qConf.getName()).thenReturn("test"); + Map<String,Object> attributes = new HashMap<String, Object>(); + attributes.put(Queue.ID, UUID.randomUUID()); + attributes.put(Queue.NAME, getTestName()); + attributes.put(Queue.MESSAGE_GROUP_KEY,"mykey"); + attributes.put(Queue.MESSAGE_GROUP_SHARED_GROUPS, true); - AMQQueue queue = _queueFactory.createAMQQueueImpl(qConf); + AMQQueue queue = _queueFactory.createQueue(attributes); assertEquals("mykey", queue.getAttribute(Queue.MESSAGE_GROUP_KEY)); assertEquals(Boolean.TRUE, queue.getAttribute(Queue.MESSAGE_GROUP_SHARED_GROUPS)); } diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueListTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueListTest.java index 7eda8ea4fa..34371b1b11 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueListTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueListTest.java @@ -28,8 +28,8 @@ import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.model.Queue; - import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.test.utils.QpidTestCase; @@ -49,6 +49,7 @@ public class PriorityQueueListTest extends QpidTestCase protected void setUp() { + BrokerTestHelper.setUp(); QueueEntry[] entries = new QueueEntry[PRIORITIES.length]; Map<String,Object> queueAttributes = new HashMap<String, Object>(); queueAttributes.put(Queue.ID, UUID.randomUUID()); @@ -81,6 +82,19 @@ public class PriorityQueueListTest extends QpidTestCase _priority5message2 = entries[2]; } + @Override + public void tearDown() throws Exception + { + try + { + super.tearDown(); + } + finally + { + BrokerTestHelper.tearDown(); + } + } + public void testPriorityQueueEntryCompareToItself() { //check messages compare to themselves properly diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java index 650b22ff51..76d460b296 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java @@ -37,7 +37,6 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.UUID; -import org.apache.commons.configuration.Configuration; import org.apache.qpid.common.AMQPFilterTypes; import org.apache.qpid.server.binding.BindingImpl; import org.apache.qpid.server.exchange.ExchangeImpl; @@ -71,7 +70,6 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest private String _storePath; private String _storeName; private MessageStore _messageStore; - private Configuration _configuration; private VirtualHost _virtualHost; private ConfigurationRecoveryHandler _recoveryHandler; @@ -88,19 +86,22 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest private UUID _queueId; private UUID _exchangeId; private DurableConfigurationStore _configStore; + protected Map<String, Object> _messageStoreSettings; public void setUp() throws Exception { super.setUp(); + _messageStoreSettings = new HashMap<String, Object>(); _queueId = UUIDGenerator.generateRandomUUID(); _exchangeId = UUIDGenerator.generateRandomUUID(); _storeName = getName(); _storePath = TMP_FOLDER + File.separator + _storeName; + _messageStoreSettings.put(MessageStore.STORE_PATH, _storePath); FileUtils.delete(new File(_storePath), true); setTestSystemProperty("QPID_WORK", TMP_FOLDER); - _configuration = mock(Configuration.class); + _recoveryHandler = mock(ConfigurationRecoveryHandler.class); _storedMessageRecoveryHandler = mock(StoredMessageRecoveryHandler.class); _logRecoveryHandler = mock(TransactionLogRecoveryHandler.class); @@ -118,9 +119,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest when(_exchange.getId()).thenReturn(_exchangeId); when(_exchange.getExchangeType()).thenReturn(mock(ExchangeType.class)); when(_exchange.getEventLogger()).thenReturn(new EventLogger()); - when(_configuration.getString(eq(MessageStoreConstants.ENVIRONMENT_PATH_PROPERTY), anyString())).thenReturn( - _storePath); - when(_virtualHost.getAttribute(eq(VirtualHost.STORE_PATH))).thenReturn(_storePath); + when(_virtualHost.getMessageStoreSettings()).thenReturn(_messageStoreSettings); _bindingArgs = new HashMap<String, Object>(); String argKey = AMQPFilterTypes.JMS_SELECTOR.toString(); diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/JsonFileConfigStoreTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/JsonFileConfigStoreTest.java index 224a22687f..96609ae992 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/JsonFileConfigStoreTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/JsonFileConfigStoreTest.java @@ -48,6 +48,7 @@ public class JsonFileConfigStoreTest extends QpidTestCase private final ConfigurationRecoveryHandler _recoveryHandler = mock(ConfigurationRecoveryHandler.class); private VirtualHost _virtualHost; private JsonFileConfigStore _store; + private HashMap<String, Object> _configurationStoreSettings; @Override public void setUp() throws Exception @@ -56,7 +57,10 @@ public class JsonFileConfigStoreTest extends QpidTestCase removeStoreFile(); _virtualHost = mock(VirtualHost.class); when(_virtualHost.getName()).thenReturn(getName()); - when(_virtualHost.getAttribute(VirtualHost.CONFIG_STORE_PATH)).thenReturn(TMP_FOLDER); + _configurationStoreSettings = new HashMap<String, Object>(); + _configurationStoreSettings.put(JsonFileConfigStore.STORE_TYPE, JsonFileConfigStore.TYPE); + _configurationStoreSettings.put(JsonFileConfigStore.STORE_PATH, TMP_FOLDER); + when(_virtualHost.getConfigurationStoreSettings()).thenReturn(_configurationStoreSettings); _store = new JsonFileConfigStore(); } @@ -77,7 +81,7 @@ public class JsonFileConfigStoreTest extends QpidTestCase public void testNoStorePath() throws Exception { - when(_virtualHost.getAttribute(VirtualHost.CONFIG_STORE_PATH)).thenReturn(null); + _configurationStoreSettings.put(JsonFileConfigStore.STORE_PATH, null); try { _store.configureConfigStore(_virtualHost, _recoveryHandler); @@ -92,7 +96,7 @@ public class JsonFileConfigStoreTest extends QpidTestCase public void testInvalidStorePath() throws Exception { - when(_virtualHost.getAttribute(VirtualHost.CONFIG_STORE_PATH)).thenReturn(System.getProperty("file.separator")); + _configurationStoreSettings.put(JsonFileConfigStore.STORE_PATH, System.getProperty("file.separator")); try { _store.configureConfigStore(_virtualHost, _recoveryHandler); diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java index 7a4f92f0ca..908f3fe6e1 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java @@ -20,6 +20,9 @@ */ package org.apache.qpid.server.store; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import java.io.File; import java.nio.ByteBuffer; import java.util.ArrayList; @@ -29,13 +32,10 @@ import java.util.UUID; import org.apache.log4j.Logger; import org.apache.qpid.server.message.EnqueueableMessage; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.store.MessageStoreRecoveryHandler.StoredMessageRecoveryHandler; import org.apache.qpid.test.utils.QpidTestCase; import org.apache.qpid.util.FileUtils; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - public abstract class MessageStoreQuotaEventsTestBase extends QpidTestCase implements EventListener, TransactionLogResource { private static final Logger _logger = Logger.getLogger(MessageStoreQuotaEventsTestBase.class); @@ -49,9 +49,7 @@ public abstract class MessageStoreQuotaEventsTestBase extends QpidTestCase imple private UUID _transactionResource; protected abstract MessageStore createStore() throws Exception; - - protected abstract void applyStoreSpecificConfiguration(VirtualHost virtualHost); - + protected abstract VirtualHost<?> createVirtualHost(String storeLocation); protected abstract int getNumberOfMessagesToFillStore(); @Override @@ -63,21 +61,21 @@ public abstract class MessageStoreQuotaEventsTestBase extends QpidTestCase imple FileUtils.delete(_storeLocation, true); - VirtualHost vhost = mock(VirtualHost.class); - when(vhost.getAttribute(eq(VirtualHost.STORE_PATH))).thenReturn(_storeLocation.getAbsolutePath()); - when(vhost.getName()).thenReturn("test"); - - applyStoreSpecificConfiguration(vhost); + VirtualHost<?> vhost = createVirtualHost(_storeLocation.getAbsolutePath()); _store = createStore(); ((DurableConfigurationStore)_store).configureConfigStore(vhost, null); - _store.configureMessageStore(vhost, mock(MessageStoreRecoveryHandler.class), null); + MessageStoreRecoveryHandler recoveryHandler = mock(MessageStoreRecoveryHandler.class); + when(recoveryHandler.begin()).thenReturn(mock(StoredMessageRecoveryHandler.class)); + _store.configureMessageStore(vhost, recoveryHandler, null); + _store.activate(); _transactionResource = UUID.randomUUID(); _events = new ArrayList<Event>(); _store.addEventListener(this, Event.PERSISTENT_MESSAGE_SIZE_OVERFULL, Event.PERSISTENT_MESSAGE_SIZE_UNDERFULL); } + @Override public void tearDown() throws Exception { diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/StateManagerTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/StateManagerTest.java index 3ee98f9a21..1996620950 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/StateManagerTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/StateManagerTest.java @@ -22,6 +22,7 @@ package org.apache.qpid.server.store; import java.util.EnumSet; + import junit.framework.TestCase; public class StateManagerTest extends TestCase implements EventListener @@ -115,7 +116,7 @@ public class StateManagerTest extends TestCase implements EventListener performValidTransition(StateManager.INITIALISE_COMPLETE); performValidTransition(StateManager.CLOSE_INITIALISED); performValidTransition(StateManager.CLOSE_COMPLETE); - + _manager = new StateManager(this); performValidTransition(StateManager.INITIALISE); performValidTransition(StateManager.INITIALISE_COMPLETE); @@ -141,13 +142,13 @@ public class StateManagerTest extends TestCase implements EventListener performInvalidTransitions(StateManager.INITIALISE, State.INITIALISED); performInvalidTransitions(StateManager.INITIALISE_COMPLETE, State.ACTIVATING, State.CLOSING); - performInvalidTransitions(StateManager.ACTIVATE, State.ACTIVE); + performInvalidTransitions(StateManager.ACTIVATE, State.ACTIVE, State.CLOSING); performInvalidTransitions(StateManager.ACTIVATE_COMPLETE, State.QUIESCING, State.CLOSING, State.INITIALISED); performInvalidTransitions(StateManager.QUIESCE, State.QUIESCED); performInvalidTransitions(StateManager.QUIESCE_COMPLETE, State.ACTIVATING, State.CLOSING); performInvalidTransitions(StateManager.CLOSE_QUIESCED, State.CLOSED); performInvalidTransitions(StateManager.CLOSE_COMPLETE); - + } private void performInvalidTransitions(StateManager.Transition preTransition, State... validEndStates) @@ -156,7 +157,7 @@ public class StateManagerTest extends TestCase implements EventListener { performValidTransition(preTransition); } - + EnumSet<State> endStates = EnumSet.allOf(State.class); if(validEndStates != null) @@ -166,13 +167,13 @@ public class StateManagerTest extends TestCase implements EventListener endStates.remove(state); } } - + for(State invalidEndState : endStates) { performInvalidStateTransition(invalidEndState); } - + } private void performInvalidStateTransition(State invalidEndState) diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStoreFactory.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStoreFactory.java index fd2d4215ab..73e14389d5 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStoreFactory.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStoreFactory.java @@ -21,9 +21,8 @@ package org.apache.qpid.server.store; -import java.util.Collections; import java.util.Map; -import org.apache.commons.configuration.Configuration; + import org.apache.qpid.server.plugin.MessageStoreFactory; public class TestMemoryMessageStoreFactory implements MessageStoreFactory @@ -42,12 +41,6 @@ public class TestMemoryMessageStoreFactory implements MessageStoreFactory } @Override - public Map<String, Object> convertStoreConfiguration(Configuration configuration) - { - return Collections.emptyMap(); - } - - @Override public void validateAttributes(Map<String, Object> attributes) { } diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java index 6b9bb08aa9..7d4dcd0280 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java @@ -33,6 +33,7 @@ import java.util.concurrent.atomic.AtomicInteger; */ public class TestableMemoryMessageStore extends TestMemoryMessageStore { + public static final String TYPE = "TestableMemory"; private final Map<Long, AMQQueue> _messages = new HashMap<Long, AMQQueue>(); private final AtomicInteger _messageCount = new AtomicInteger(0); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/ExchangeConfiguration.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStoreFactory.java index 6cbaf26480..ba9b7c155e 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/ExchangeConfiguration.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStoreFactory.java @@ -7,9 +7,9 @@ * 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 @@ -18,41 +18,30 @@ * under the License. * */ -package org.apache.qpid.server.configuration; - -import org.apache.commons.configuration.Configuration; +package org.apache.qpid.server.store; -public class ExchangeConfiguration -{ +import java.util.Map; - private Configuration _config; - private String _name; - - public ExchangeConfiguration(String name, Configuration subset) - { - _name = name; - _config = subset; - } - - public String getName() - { - return _name; - } +import org.apache.qpid.server.plugin.MessageStoreFactory; +public class TestableMemoryMessageStoreFactory implements MessageStoreFactory +{ + @Override public String getType() { - return _config.getString("type","direct"); + return TestableMemoryMessageStore.TYPE; } - public boolean getDurable() + @Override + public MessageStore createMessageStore() { - return _config.getBoolean("durable", false); + return new TestableMemoryMessageStore(); } - public boolean getAutoDelete() + @Override + public void validateAttributes(Map<String, Object> attributes) { - return _config.getBoolean("autodelete",false); } } diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java index 857cc60a7e..fd56f3fa1c 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java @@ -29,14 +29,11 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.qpid.server.exchange.ExchangeImpl; import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.protocol.AMQConnectionModel; import org.apache.qpid.server.protocol.AMQSessionModel; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.configuration.store.JsonConfigurationEntryStore; import org.apache.qpid.server.exchange.DefaultExchangeFactory; import org.apache.qpid.server.model.Broker; @@ -45,9 +42,12 @@ import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.security.SubjectCreator; import org.apache.qpid.server.stats.StatisticsGatherer; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.TestMemoryMessageStore; import org.apache.qpid.server.store.TestableMemoryMessageStore; import org.apache.qpid.server.virtualhost.StandardVirtualHostFactory; import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.plugin.PluggableFactoryLoader; import org.apache.qpid.server.plugin.VirtualHostFactory; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; import org.apache.qpid.server.virtualhost.QueueExistsException; @@ -82,23 +82,14 @@ public class BrokerTestHelper { } - public static VirtualHost createVirtualHost(VirtualHostConfiguration virtualHostConfiguration, VirtualHostRegistry virtualHostRegistry) + public static VirtualHost createVirtualHost(VirtualHostRegistry virtualHostRegistry, org.apache.qpid.server.model.VirtualHost modelVHost) throws Exception { - return createVirtualHost(virtualHostConfiguration, virtualHostRegistry, mock(org.apache.qpid.server.model.VirtualHost.class)); - } - - public static VirtualHost createVirtualHost(VirtualHostConfiguration virtualHostConfiguration, VirtualHostRegistry virtualHostRegistry, org.apache.qpid.server.model.VirtualHost modelVHost) - throws Exception - { - StatisticsGatherer statisticsGatherer = mock(StatisticsGatherer.class); - final VirtualHostFactory factory = - virtualHostConfiguration == null ? new StandardVirtualHostFactory() - : VirtualHostFactory.FACTORIES.get(virtualHostConfiguration.getType()); + String hostType = modelVHost.getType(); + VirtualHostFactory factory = new PluggableFactoryLoader<VirtualHostFactory>(VirtualHostFactory.class).get(hostType); VirtualHost host = factory.createVirtualHost(virtualHostRegistry, - statisticsGatherer, + mock(StatisticsGatherer.class), new SecurityManager(mock(Broker.class), false), - virtualHostConfiguration, modelVHost); if(virtualHostRegistry != null) { @@ -107,29 +98,23 @@ public class BrokerTestHelper return host; } - public static VirtualHost createVirtualHost(VirtualHostConfiguration virtualHostConfiguration) throws Exception + public static VirtualHost createVirtualHost(String name) throws Exception { - - return createVirtualHost(virtualHostConfiguration, new VirtualHostRegistry(new EventLogger())); + return createVirtualHost(name, new VirtualHostRegistry(new EventLogger())); } public static VirtualHost createVirtualHost(String name, VirtualHostRegistry virtualHostRegistry) throws Exception { - VirtualHostConfiguration vhostConfig = createVirtualHostConfiguration(name); - return createVirtualHost(vhostConfig, virtualHostRegistry); - } + org.apache.qpid.server.model.VirtualHost virtualHost = mock(org.apache.qpid.server.model.VirtualHost.class); + when(virtualHost.getType()).thenReturn(StandardVirtualHostFactory.TYPE); + when(virtualHost.getAttribute(org.apache.qpid.server.model.VirtualHost.TYPE)).thenReturn(StandardVirtualHostFactory.TYPE); - public static VirtualHost createVirtualHost(String name) throws Exception - { - VirtualHostConfiguration configuration = createVirtualHostConfiguration(name); - return createVirtualHost(configuration); - } + Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); + messageStoreSettings.put(MessageStore.STORE_TYPE, TestableMemoryMessageStore.TYPE); - private static VirtualHostConfiguration createVirtualHostConfiguration(String name) throws ConfigurationException - { - VirtualHostConfiguration vhostConfig = new VirtualHostConfiguration(name, new PropertiesConfiguration(), createBrokerMock()); - vhostConfig.setMessageStoreClass(TestableMemoryMessageStore.class.getName()); - return vhostConfig; + when(virtualHost.getMessageStoreSettings()).thenReturn(messageStoreSettings); + when(virtualHost.getName()).thenReturn(name); + return createVirtualHost(virtualHostRegistry, virtualHost); } public static AMQSessionModel createSession(int channelId, AMQConnectionModel connection) @@ -189,5 +174,4 @@ public class BrokerTestHelper return queue; } - } diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java index f3f4b0d06e..04a218d024 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java @@ -23,7 +23,6 @@ package org.apache.qpid.server.virtualhost; import java.util.Collection; import java.util.Map; import java.util.concurrent.ScheduledFuture; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.connection.IConnectionRegistry; import org.apache.qpid.server.exchange.ExchangeImpl; @@ -73,11 +72,6 @@ public class MockVirtualHost implements VirtualHost return null; } - public VirtualHostConfiguration getConfiguration() - { - return null; - } - public IConnectionRegistry getConnectionRegistry() { return null; @@ -370,4 +364,10 @@ public class MockVirtualHost implements VirtualHost { return null; } + + @Override + public boolean getDefaultDeadLetterQueueEnabled() + { + return false; + } } diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/StandardVirtualHostTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/StandardVirtualHostTest.java index f081268337..e31cb16d27 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/StandardVirtualHostTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/StandardVirtualHostTest.java @@ -20,45 +20,47 @@ */ package org.apache.qpid.server.virtualhost; -import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.PropertiesConfiguration; +import java.io.File; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; import org.apache.qpid.server.binding.BindingImpl; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; - import org.apache.qpid.server.exchange.AbstractExchange; import org.apache.qpid.server.exchange.ExchangeImpl; +import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Model; +import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.stats.StatisticsGatherer; -import org.apache.qpid.server.store.TestMemoryMessageStore; +import org.apache.qpid.server.store.ConfigurationRecoveryHandler; +import org.apache.qpid.server.store.DurableConfigurationStore; +import org.apache.qpid.server.store.JsonFileConfigStore; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.TestableMemoryMessageStore; import org.apache.qpid.server.util.BrokerTestHelper; -import org.apache.qpid.server.util.ServerScopedRuntimeException; import org.apache.qpid.test.utils.QpidTestCase; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; +import org.apache.qpid.test.utils.TestFileUtils; +import org.apache.qpid.util.FileUtils; +import org.codehaus.jackson.map.ObjectMapper; public class StandardVirtualHostTest extends QpidTestCase { private VirtualHostRegistry _virtualHostRegistry; + private File _storeFolder; @Override public void setUp() throws Exception { super.setUp(); BrokerTestHelper.setUp(); + _storeFolder = TestFileUtils.createTestDirectory(".tmp.store", true); } @Override @@ -75,6 +77,7 @@ public class StandardVirtualHostTest extends QpidTestCase { BrokerTestHelper.tearDown(); super.tearDown(); + FileUtils.delete(_storeFolder, false); } } @@ -106,25 +109,23 @@ public class StandardVirtualHostTest extends QpidTestCase { final String queueName = getName(); final String customBinding = "custom-binding"; - File config = writeConfigFile(queueName, queueName, null, false, new String[]{customBinding}); + writeConfigFile(queueName, queueName, null, false, new String[]{customBinding}); try { - createVirtualHost(queueName, config); + createVirtualHost(queueName); fail("virtualhost creation should have failed due to illegal configuration"); } - catch (ServerScopedRuntimeException e) + catch (IllegalConfigurationException e) { - Throwable cause = e.getCause(); - assertNotNull(cause); - assertEquals("Attempt to bind queue '" + queueName + "' with binding key(s) [" + customBinding + "] without specifying an exchange", cause.getMessage()); + // pass } } public void testVirtualHostBecomesActive() throws Exception { - File config = writeConfigFile(getName(), getName(), getName() +".direct", false, new String[0]); - VirtualHost vhost = createVirtualHost(getName(), config); + writeConfigFile(getName(), getName(), getName() +".direct", false, new String[0]); + VirtualHost vhost = createVirtualHost(getName()); assertNotNull(vhost); assertEquals(State.ACTIVE, vhost.getState()); } @@ -132,15 +133,15 @@ public class StandardVirtualHostTest extends QpidTestCase public void testVirtualHostHavingStoreSetAsTypeBecomesActive() throws Exception { String virtualHostName = getName(); - VirtualHost host = createVirtualHostUsingStoreType(virtualHostName); + VirtualHost host = createVirtualHost(virtualHostName); assertNotNull(host); assertEquals(State.ACTIVE, host.getState()); } public void testVirtualHostBecomesStoppedOnClose() throws Exception { - File config = writeConfigFile(getName(), getName(), getName() +".direct", false, new String[0]); - VirtualHost vhost = createVirtualHost(getName(), config); + writeConfigFile(getName(), getName(), getName() +".direct", false, new String[0]); + VirtualHost vhost = createVirtualHost(getName()); assertNotNull(vhost); assertEquals(State.ACTIVE, vhost.getState()); vhost.close(); @@ -151,7 +152,7 @@ public class StandardVirtualHostTest extends QpidTestCase public void testVirtualHostHavingStoreSetAsTypeBecomesStoppedOnClose() throws Exception { String virtualHostName = getName(); - VirtualHost host = createVirtualHostUsingStoreType(virtualHostName); + VirtualHost host = createVirtualHost(virtualHostName); assertNotNull(host); assertEquals(State.ACTIVE, host.getState()); host.close(); @@ -166,33 +167,16 @@ public class StandardVirtualHostTest extends QpidTestCase { final String queueName = getName(); final String exchangeName = "made-up-exchange"; - File config = writeConfigFile(queueName, queueName, exchangeName, true, new String[0]); - - try - { - createVirtualHost(queueName, config); - fail("virtualhost creation should have failed due to illegal configuration"); - } - catch (ServerScopedRuntimeException e) - { - Throwable cause = e.getCause(); - assertNotNull(cause); - assertEquals("Attempt to bind queue '" + queueName + "' to unknown exchange:" + exchangeName, cause.getMessage()); - } - } + writeConfigFile(queueName, queueName, exchangeName, true, new String[0]); - public void testCreateVirtualHostWithoutConfigurationInConfigFile() throws Exception - { - File config = writeConfigFile(getName(), getName(), getName() +".direct", false, new String[0]); - String hostName = getName() + "-not-existing"; try { - createVirtualHost(hostName, config); + createVirtualHost(queueName); fail("virtualhost creation should have failed due to illegal configuration"); } - catch (RuntimeException e) + catch (IllegalConfigurationException e) { - assertEquals("No configuration found for virtual host '" + hostName + "' in " + config.getAbsolutePath(), e.getMessage()); + // pass } } @@ -205,8 +189,8 @@ public class StandardVirtualHostTest extends QpidTestCase Map<String, String[]> bindingArguments = new HashMap<String, String[]>(); bindingArguments.put("ping", new String[]{"x-filter-jms-selector=select=1", "x-qpid-no-local"}); bindingArguments.put("pong", new String[]{"x-filter-jms-selector=select='pong'"}); - File config = writeConfigFile(vhostName, queueName, exchangeName, false, new String[]{"ping","pong"}, bindingArguments); - VirtualHost vhost = createVirtualHost(vhostName, config); + writeConfigFile(vhostName, queueName, exchangeName, false, new String[]{"ping","pong"}, bindingArguments); + VirtualHost vhost = createVirtualHost(vhostName); ExchangeImpl exch = vhost.getExchange(getName() +".direct"); Collection<BindingImpl> bindings = ((AbstractExchange)exch).getBindings(); @@ -246,8 +230,8 @@ public class StandardVirtualHostTest extends QpidTestCase String vhostName = getName(); String queueName = getName(); - File config = writeConfigFile(vhostName, queueName, exchangeName, false, routingKeys); - VirtualHost vhost = createVirtualHost(vhostName, config); + writeConfigFile(vhostName, queueName, exchangeName, false, routingKeys); + VirtualHost vhost = createVirtualHost(vhostName); assertNotNull("virtualhost should exist", vhost); AMQQueue queue = vhost.getQueue(queueName); @@ -263,16 +247,26 @@ public class StandardVirtualHostTest extends QpidTestCase } - private VirtualHost createVirtualHost(String vhostName, File config) throws Exception + private VirtualHost createVirtualHost(String virtualHostName) throws Exception { - Broker broker = BrokerTestHelper.createBrokerMock(); + Broker<?> broker = BrokerTestHelper.createBrokerMock(); + _virtualHostRegistry = broker.getVirtualHostRegistry(); - VirtualHostConfiguration configuration = new VirtualHostConfiguration(vhostName, config, broker); - VirtualHost host = new StandardVirtualHostFactory().createVirtualHost(_virtualHostRegistry, mock(StatisticsGatherer.class), new SecurityManager(mock(Broker.class), false), configuration, - mock(org.apache.qpid.server.model.VirtualHost.class)); - _virtualHostRegistry.registerVirtualHost(host); + org.apache.qpid.server.model.VirtualHost<?> model = mock(org.apache.qpid.server.model.VirtualHost.class); + Map<String, Object> configurationStoreSettings = new HashMap<String, Object>(); + when(model.getConfigurationStoreSettings()).thenReturn(configurationStoreSettings); + configurationStoreSettings.put(DurableConfigurationStore.STORE_TYPE, JsonFileConfigStore.TYPE); + configurationStoreSettings.put(DurableConfigurationStore.STORE_PATH, _storeFolder.getAbsolutePath()); + + Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); + messageStoreSettings.put(MessageStore.STORE_TYPE, TestableMemoryMessageStore.TYPE); + when(model.getMessageStoreSettings()).thenReturn(messageStoreSettings); + when(model.getName()).thenReturn(virtualHostName); + VirtualHost host = new StandardVirtualHostFactory().createVirtualHost(_virtualHostRegistry, mock(StatisticsGatherer.class), + new SecurityManager(broker, false), model); + _virtualHostRegistry.registerVirtualHost(host); return host; } @@ -285,95 +279,83 @@ public class StandardVirtualHostTest extends QpidTestCase * @param dontDeclare if true then don't declare the exchange, even if its name is non-null * @param routingKeys routingKeys to bind the queue with (empty array = none) * @return + * @throws Exception */ - private File writeConfigFile(String vhostName, String queueName, String exchangeName, boolean dontDeclare, String[] routingKeys) + private void writeConfigFile(String vhostName, String queueName, String exchangeName, boolean dontDeclare, String[] routingKeys) throws Exception { - return writeConfigFile(vhostName, queueName, exchangeName, dontDeclare, routingKeys, null); + writeConfigFile(vhostName, queueName, exchangeName, dontDeclare, routingKeys, null); } - private File writeConfigFile(String vhostName, String queueName, String exchangeName, boolean dontDeclare, String[] routingKeys, Map<String, String[]> bindingArguments) + private void writeConfigFile(String vhostName, String queueName, String exchangeName, boolean dontDeclare, + String[] routingKeys, Map<String, String[]> bindingArguments) throws Exception { - File tmpFile = null; - try + Map<String, Object> data = new HashMap<String, Object>(); + data.put("modelVersion", Model.MODEL_VERSION); + data.put("configVersion", org.apache.qpid.server.model.VirtualHost.CURRENT_CONFIG_VERSION); + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.writeValue(new File(_storeFolder, vhostName + ".json"), data); + + JsonFileConfigStore store = new JsonFileConfigStore(); + org.apache.qpid.server.model.VirtualHost<?> virtualHost = mock(org.apache.qpid.server.model.VirtualHost.class); + when(virtualHost.getName()).thenReturn(vhostName); + Map<String, Object> configurationStoreSettings = new HashMap<String, Object>(); + when(virtualHost.getConfigurationStoreSettings()).thenReturn(configurationStoreSettings); + configurationStoreSettings.put(DurableConfigurationStore.STORE_TYPE, JsonFileConfigStore.TYPE); + configurationStoreSettings.put(DurableConfigurationStore.STORE_PATH, _storeFolder.getAbsolutePath()); + + ConfigurationRecoveryHandler recoveryHandler = mock(ConfigurationRecoveryHandler.class); + when(recoveryHandler.completeConfigurationRecovery()).thenReturn(org.apache.qpid.server.model.VirtualHost.CURRENT_CONFIG_VERSION); + store.configureConfigStore(virtualHost , recoveryHandler ); + + UUID exchangeId = UUIDGenerator.generateExchangeUUID(exchangeName == null? "amq.direct" : exchangeName, vhostName); + if(exchangeName != null && !dontDeclare) { - tmpFile = File.createTempFile(getName(), ".tmp"); - tmpFile.deleteOnExit(); - - FileWriter fstream = new FileWriter(tmpFile); - BufferedWriter writer = new BufferedWriter(fstream); - - //extra outer tag to please Commons Configuration - - writer.write("<virtualhosts>"); - writer.write(" <default>" + vhostName + "</default>"); - writer.write(" <virtualhost>"); - writer.write(" <name>" + vhostName + "</name>"); - writer.write(" <" + vhostName + ">"); - writer.write(" <type>" + StandardVirtualHostFactory.TYPE + "</type>"); - writer.write(" <store>"); - writer.write(" <class>" + TestMemoryMessageStore.class.getName() + "</class>"); - writer.write(" </store>"); - if(exchangeName != null && !dontDeclare) - { - writer.write(" <exchanges>"); - writer.write(" <exchange>"); - writer.write(" <type>direct</type>"); - writer.write(" <name>" + exchangeName + "</name>"); - writer.write(" </exchange>"); - writer.write(" </exchanges>"); - } - writer.write(" <queues>"); - writer.write(" <queue>"); - writer.write(" <name>" + queueName + "</name>"); - writer.write(" <" + queueName + ">"); - if(exchangeName != null) - { - writer.write(" <exchange>" + exchangeName + "</exchange>"); - } - for(String routingKey: routingKeys) + Map<String, Object> exchangeAttributes = new HashMap<String, Object>(); + exchangeAttributes.put(org.apache.qpid.server.model.Exchange.NAME, exchangeName); + exchangeAttributes.put(org.apache.qpid.server.model.Exchange.TYPE, "direct"); + exchangeAttributes.put(org.apache.qpid.server.model.Exchange.DURABLE, true); + store.create(exchangeId, org.apache.qpid.server.model.Exchange.class.getSimpleName(), exchangeAttributes); + } + + UUID queueId = UUID.randomUUID(); + Map<String, Object> queueAttributes = new HashMap<String, Object>(); + queueAttributes.put(org.apache.qpid.server.model.Queue.NAME, queueName); + queueAttributes.put(org.apache.qpid.server.model.Queue.DURABLE, true); + store.create(queueId, org.apache.qpid.server.model.Queue.class.getSimpleName(), queueAttributes); + + Map<String, Object> bindingAttributes = new HashMap<String, Object>(); + bindingAttributes.put(org.apache.qpid.server.model.Binding.NAME, queueName); + bindingAttributes.put(org.apache.qpid.server.model.Binding.QUEUE, queueId); + bindingAttributes.put(org.apache.qpid.server.model.Binding.EXCHANGE, exchangeId ); + store.create(UUID.randomUUID(), org.apache.qpid.server.model.Binding.class.getSimpleName(), bindingAttributes); + + for (int i = 0; i < routingKeys.length; i++) + { + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(org.apache.qpid.server.model.Binding.NAME, routingKeys[i]); + attributes.put(org.apache.qpid.server.model.Binding.QUEUE, queueId); + attributes.put(org.apache.qpid.server.model.Binding.EXCHANGE, exchangeId ); + if (bindingArguments != null && bindingArguments.containsKey(routingKeys[i])) { - writer.write(" <routingKey>" + routingKey + "</routingKey>\n"); - if (bindingArguments!= null && bindingArguments.containsKey(routingKey)) + String[] args = (String[])bindingArguments.get(routingKeys[i]); + Map<String, Object> arguments = new HashMap<String, Object>(); + for (int j = 0; j < args.length; j++) { - writer.write(" <" + routingKey + ">\n"); - String[] arguments = (String[])bindingArguments.get(routingKey); - for (String argument : arguments) + int pos = args[j].indexOf('='); + if (pos == -1) { - writer.write(" <bindingArgument>" + argument + "</bindingArgument>\n"); + arguments.put(args[j], null); + } + else + { + arguments.put(args[j].substring(0, pos), args[j].substring(pos + 1)); } - writer.write(" </" + routingKey + ">\n"); } + attributes.put(org.apache.qpid.server.model.Binding.ARGUMENTS, arguments ); } - writer.write(" </" + queueName + ">"); - writer.write(" </queue>"); - writer.write(" </queues>"); - writer.write(" </" + vhostName + ">"); - writer.write(" </virtualhost>"); - writer.write("</virtualhosts>"); - - writer.flush(); - writer.close(); - } - catch (IOException e) - { - fail("Unable to create virtualhost configuration"); + store.create(UUID.randomUUID(), org.apache.qpid.server.model.Binding.class.getSimpleName(), attributes); } - - return tmpFile; + store.close(); } - private VirtualHost createVirtualHostUsingStoreType(String virtualHostName) throws ConfigurationException, Exception - { - Broker broker = BrokerTestHelper.createBrokerMock(); - _virtualHostRegistry = broker.getVirtualHostRegistry(); - - Configuration config = new PropertiesConfiguration(); - VirtualHostConfiguration configuration = new VirtualHostConfiguration(virtualHostName, config, broker); - final org.apache.qpid.server.model.VirtualHost virtualHost = mock(org.apache.qpid.server.model.VirtualHost.class); - when(virtualHost.getAttribute(eq(org.apache.qpid.server.model.VirtualHost.STORE_TYPE))).thenReturn(TestMemoryMessageStore.TYPE); - VirtualHost host = new StandardVirtualHostFactory().createVirtualHost(_virtualHostRegistry, mock(StatisticsGatherer.class), new SecurityManager(mock(Broker.class), false), configuration, - virtualHost); - _virtualHostRegistry.registerVirtualHost(host); - return host; - } } diff --git a/qpid/java/broker-core/src/test/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory b/qpid/java/broker-core/src/test/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory index 9512fb8117..48241614d8 100644 --- a/qpid/java/broker-core/src/test/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory +++ b/qpid/java/broker-core/src/test/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory @@ -17,3 +17,4 @@ # under the License. # org.apache.qpid.server.store.TestMemoryMessageStoreFactory +org.apache.qpid.server.store.TestableMemoryMessageStoreFactory
\ No newline at end of file diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java index f6d8b04880..5f5e12d435 100644 --- a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java +++ b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java @@ -29,7 +29,6 @@ import java.util.Set; import javax.security.auth.Subject; -import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.lang.ObjectUtils; import org.apache.log4j.Logger; import org.apache.qpid.server.configuration.IllegalConfigurationException; @@ -64,7 +63,7 @@ public class DefaultAccessControl implements AccessControl _aclFile = new File(fileName); } - DefaultAccessControl(RuleSet rs) throws ConfigurationException + DefaultAccessControl(RuleSet rs) { _ruleSet = rs; _eventLogger = rs; diff --git a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/PlainConfigurationTest.java b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/PlainConfigurationTest.java index 1440904c74..6ac21f856a 100644 --- a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/PlainConfigurationTest.java +++ b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/PlainConfigurationTest.java @@ -36,12 +36,6 @@ import org.apache.qpid.server.security.access.Operation; import static org.mockito.Mockito.mock; -/** - * These tests check that the ACL file parsing works correctly. - * - * For each message that can be returned in a {@link ConfigurationException}, an ACL file is created that should trigger this - * particular message. - */ public class PlainConfigurationTest extends TestCase { private PlainConfiguration writeACLConfig(String...aclData) throws Exception diff --git a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlTest.java b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlTest.java index 74ea7639ff..3a36ddef2c 100644 --- a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlTest.java +++ b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlTest.java @@ -31,7 +31,6 @@ import javax.security.auth.Subject; import junit.framework.TestCase; -import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.connection.ConnectionPrincipal; import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.logging.EventLoggerProvider; @@ -68,12 +67,12 @@ public class DefaultAccessControlTest extends TestCase _plugin = null; } - private void setUpGroupAccessControl() throws ConfigurationException + private void setUpGroupAccessControl() { configureAccessControl(createGroupRuleSet()); } - private void configureAccessControl(final RuleSet rs) throws ConfigurationException + private void configureAccessControl(final RuleSet rs) { _plugin = new DefaultAccessControl(rs); } @@ -98,7 +97,7 @@ public class DefaultAccessControlTest extends TestCase /** * ACL plugin must always abstain if there is no subject attached to the thread. */ - public void testNoSubjectAlwaysAbstains() throws ConfigurationException + public void testNoSubjectAlwaysAbstains() { setUpGroupAccessControl(); final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); @@ -109,7 +108,7 @@ public class DefaultAccessControlTest extends TestCase * Tests that an allow rule expressed with a username allows an operation performed by a thread running * with the same username. */ - public void testUsernameAllowsOperation() throws ConfigurationException + public void testUsernameAllowsOperation() { setUpGroupAccessControl(); Subject.doAs(TestPrincipalUtils.createTestSubject("user1"), new PrivilegedAction<Object>() @@ -128,7 +127,7 @@ public class DefaultAccessControlTest extends TestCase * Tests that an allow rule expressed with an <b>ACL groupname</b> allows an operation performed by a thread running * by a user who belongs to the same group.. */ - public void testGroupMembershipAllowsOperation() throws ConfigurationException + public void testGroupMembershipAllowsOperation() { setUpGroupAccessControl(); @@ -141,7 +140,7 @@ public class DefaultAccessControlTest extends TestCase * Tests that a deny rule expressed with a <b>groupname</b> denies an operation performed by a thread running * by a user who belongs to the same group. */ - public void testGroupMembershipDeniesOperation() throws ConfigurationException + public void testGroupMembershipDeniesOperation() { setUpGroupAccessControl(); authoriseAndAssertResult(Result.DENIED, "user3", DENIED_GROUP); @@ -150,7 +149,7 @@ public class DefaultAccessControlTest extends TestCase /** * Tests that the catch all deny denies the operation and logs with the logging actor. */ - public void testCatchAllRuleDeniesUnrecognisedUsername() throws ConfigurationException + public void testCatchAllRuleDeniesUnrecognisedUsername() { setUpGroupAccessControl(); Subject.doAs(TestPrincipalUtils.createTestSubject("unknown", "unkgroup1", "unkgroup2"), @@ -177,7 +176,7 @@ public class DefaultAccessControlTest extends TestCase /** * Tests that a grant access method rule allows any access operation to be performed on any component */ - public void testAuthoriseAccessMethodWhenAllAccessOperationsAllowedOnAllComponents() throws ConfigurationException + public void testAuthoriseAccessMethodWhenAllAccessOperationsAllowedOnAllComponents() { final RuleSet rs = new RuleSet(mock(EventLoggerProvider.class)); @@ -203,7 +202,7 @@ public class DefaultAccessControlTest extends TestCase /** * Tests that a grant access method rule allows any access operation to be performed on a specified component */ - public void testAuthoriseAccessMethodWhenAllAccessOperationsAllowedOnSpecifiedComponent() throws ConfigurationException + public void testAuthoriseAccessMethodWhenAllAccessOperationsAllowedOnSpecifiedComponent() { final RuleSet rs = new RuleSet(mock(EventLoggerProvider.class)); @@ -303,7 +302,7 @@ public class DefaultAccessControlTest extends TestCase /** * Tests that a grant access method rule allows any access operation to be performed on a specified component */ - public void testAuthoriseAccessMethodWhenSpecifiedAccessOperationsAllowedOnSpecifiedComponent() throws ConfigurationException + public void testAuthoriseAccessMethodWhenSpecifiedAccessOperationsAllowedOnSpecifiedComponent() { final RuleSet rs = new RuleSet(mock(EventLoggerProvider.class)); @@ -340,7 +339,7 @@ public class DefaultAccessControlTest extends TestCase /** * Tests that granting of all method rights on a method allows a specified operation to be performed on any component */ - public void testAuthoriseAccessUpdateMethodWhenAllRightsGrantedOnSpecifiedMethodForAllComponents() throws ConfigurationException + public void testAuthoriseAccessUpdateMethodWhenAllRightsGrantedOnSpecifiedMethodForAllComponents() { final RuleSet rs = new RuleSet(mock(EventLoggerProvider.class)); @@ -379,7 +378,7 @@ public class DefaultAccessControlTest extends TestCase /** * Tests that granting of all method rights allows any operation to be performed on any component */ - public void testAuthoriseAccessUpdateMethodWhenAllRightsGrantedOnAllMethodsInAllComponents() throws ConfigurationException + public void testAuthoriseAccessUpdateMethodWhenAllRightsGrantedOnAllMethodsInAllComponents() { final RuleSet rs = new RuleSet(mock(EventLoggerProvider.class)); @@ -417,7 +416,7 @@ public class DefaultAccessControlTest extends TestCase /** * Tests that granting of access method rights with mask allows matching operations to be performed on the specified component */ - public void testAuthoriseAccessMethodWhenMatchingAccessOperationsAllowedOnSpecifiedComponent() throws ConfigurationException + public void testAuthoriseAccessMethodWhenMatchingAccessOperationsAllowedOnSpecifiedComponent() { final RuleSet rs = new RuleSet(mock(EventLoggerProvider.class)); diff --git a/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java b/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java index 5d56329c20..f7b65075f7 100644 --- a/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java +++ b/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java @@ -32,6 +32,8 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; +import java.util.Map; + import org.apache.log4j.Logger; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.store.AbstractJDBCMessageStore; @@ -39,7 +41,6 @@ import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.Event; import org.apache.qpid.server.store.EventListener; import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.MessageStoreConstants; import org.apache.qpid.server.store.StoreException; import org.apache.qpid.util.FileUtils; @@ -130,13 +131,26 @@ public class DerbyMessageStore extends AbstractJDBCMessageStore implements Messa { //Update to pick up QPID_WORK and use that as the default location not just derbyDB + Map<String, Object> messageStoreSettings = virtualHost.getMessageStoreSettings(); + Map<String, Object> configurationStoreSettings = virtualHost.getConfigurationStoreSettings(); _driverClass = (Class<Driver>) Class.forName(SQL_DRIVER_NAME); - String defaultPath = System.getProperty("QPID_WORK") + File.separator + "derbyDB"; - String databasePath = isConfigStoreOnly() ? (String) virtualHost.getAttribute(VirtualHost.CONFIG_STORE_PATH) : (String) virtualHost.getAttribute(VirtualHost.STORE_PATH); + String databasePath = null; + if (isConfigStoreOnly()) + { + databasePath = (String) configurationStoreSettings.get(DurableConfigurationStore.STORE_PATH); + } + else + { + if (messageStoreSettings != null) + { + databasePath = (String) messageStoreSettings.get(MessageStore.STORE_PATH); + } + } + if(databasePath == null) { - databasePath = defaultPath; + databasePath = System.getProperty("QPID_WORK") + File.separator + "derbyDB"; } if(!MEMORY_STORE_LOCATION.equals(databasePath)) @@ -154,8 +168,8 @@ public class DerbyMessageStore extends AbstractJDBCMessageStore implements Messa _storeLocation = databasePath; - Object overfullAttr = virtualHost.getAttribute(MessageStoreConstants.OVERFULL_SIZE_ATTRIBUTE); - Object underfullAttr = virtualHost.getAttribute(MessageStoreConstants.UNDERFULL_SIZE_ATTRIBUTE); + Object overfullAttr = messageStoreSettings.get(MessageStore.OVERFULL_SIZE); + Object underfullAttr = messageStoreSettings.get(MessageStore.UNDERFULL_SIZE); _persistentSizeHighThreshold = overfullAttr == null ? -1l : overfullAttr instanceof Number ? ((Number) overfullAttr).longValue() : Long.parseLong(overfullAttr.toString()); diff --git a/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java b/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java index 47a451ccf6..a3610901c5 100644 --- a/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java +++ b/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java @@ -20,9 +20,8 @@ */ package org.apache.qpid.server.store.derby; -import java.util.Collections; import java.util.Map; -import org.apache.commons.configuration.Configuration; + import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.plugin.DurableConfigurationStoreFactory; import org.apache.qpid.server.plugin.MessageStoreFactory; @@ -51,31 +50,30 @@ public class DerbyMessageStoreFactory implements MessageStoreFactory, DurableCon } @Override - public Map<String, Object> convertStoreConfiguration(Configuration configuration) - { - return Collections.emptyMap(); - } - - - @Override public void validateAttributes(Map<String, Object> attributes) { - if(getType().equals(attributes.get(VirtualHost.STORE_TYPE))) + @SuppressWarnings("unchecked") + Map<String, Object> messageStoreSettings = (Map<String, Object>) attributes.get(VirtualHost.MESSAGE_STORE_SETTINGS); + + if(getType().equals(messageStoreSettings.get(MessageStore.STORE_TYPE))) { - Object storePath = attributes.get(VirtualHost.STORE_PATH); + Object storePath = messageStoreSettings.get(MessageStore.STORE_PATH); if(!(storePath instanceof String)) { - throw new IllegalArgumentException("Attribute '"+ VirtualHost.STORE_PATH + throw new IllegalArgumentException("Setting '"+ MessageStore.STORE_PATH +"' is required and must be of type String."); } } - if(getType().equals(attributes.get(VirtualHost.CONFIG_STORE_TYPE))) + + @SuppressWarnings("unchecked") + Map<String, Object> configurationStoreSettings = (Map<String, Object>) attributes.get(VirtualHost.CONFIGURATION_STORE_SETTINGS); + if(getType().equals(configurationStoreSettings.get(DurableConfigurationStore.STORE_TYPE))) { - Object storePath = attributes.get(VirtualHost.CONFIG_STORE_PATH); + Object storePath = configurationStoreSettings.get(DurableConfigurationStore.STORE_PATH); if(!(storePath instanceof String)) { - throw new IllegalArgumentException("Attribute '"+ VirtualHost.CONFIG_STORE_PATH + throw new IllegalArgumentException("Setting '"+ DurableConfigurationStore.STORE_PATH +"' is required and must be of type String."); } diff --git a/qpid/java/broker-plugins/derby-store/src/test/java/org/apache/qpid/server/store/derby/DerbyMessageStoreQuotaEventsTest.java b/qpid/java/broker-plugins/derby-store/src/test/java/org/apache/qpid/server/store/derby/DerbyMessageStoreQuotaEventsTest.java index 479675dac1..f23b5a3e23 100644 --- a/qpid/java/broker-plugins/derby-store/src/test/java/org/apache/qpid/server/store/derby/DerbyMessageStoreQuotaEventsTest.java +++ b/qpid/java/broker-plugins/derby-store/src/test/java/org/apache/qpid/server/store/derby/DerbyMessageStoreQuotaEventsTest.java @@ -20,15 +20,17 @@ */ package org.apache.qpid.server.store.derby; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import java.util.Map; + import org.apache.log4j.Logger; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.MessageStoreConstants; import org.apache.qpid.server.store.MessageStoreQuotaEventsTestBase; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.when; - public class DerbyMessageStoreQuotaEventsTest extends MessageStoreQuotaEventsTestBase { private static final Logger _logger = Logger.getLogger(DerbyMessageStoreQuotaEventsTest.class); @@ -50,17 +52,26 @@ public class DerbyMessageStoreQuotaEventsTest extends MessageStoreQuotaEventsTes } @Override - protected void applyStoreSpecificConfiguration(VirtualHost vhost) + protected MessageStore createStore() throws Exception { - _logger.debug("Applying store specific config. overfull-sze=" + OVERFULL_SIZE + ", underfull-size=" + UNDERFULL_SIZE); - - when(vhost.getAttribute(eq(MessageStoreConstants.OVERFULL_SIZE_ATTRIBUTE))).thenReturn(OVERFULL_SIZE); - when(vhost.getAttribute(eq(MessageStoreConstants.UNDERFULL_SIZE_ATTRIBUTE))).thenReturn(UNDERFULL_SIZE); + return new DerbyMessageStore(); } @Override - protected MessageStore createStore() throws Exception + protected VirtualHost<?> createVirtualHost(String storeLocation) { - return new DerbyMessageStore(); + _logger.debug("Applying store specific config. overfull-size=" + OVERFULL_SIZE + ", underfull-size=" + UNDERFULL_SIZE); + + VirtualHost<?> vhost = mock(VirtualHost.class); + Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); + messageStoreSettings.put(MessageStore.STORE_PATH, storeLocation); + messageStoreSettings.put(MessageStore.OVERFULL_SIZE, OVERFULL_SIZE); + messageStoreSettings.put(MessageStore.UNDERFULL_SIZE, UNDERFULL_SIZE); + + when(vhost.getMessageStoreSettings()).thenReturn(messageStoreSettings ); + when(vhost.getName()).thenReturn("test"); + + return vhost; } + } diff --git a/qpid/java/broker-plugins/derby-store/src/test/java/org/apache/qpid/server/store/derby/DerbyMessageStoreTest.java b/qpid/java/broker-plugins/derby-store/src/test/java/org/apache/qpid/server/store/derby/DerbyMessageStoreTest.java index 859fad629b..e3f91cc8fb 100644 --- a/qpid/java/broker-plugins/derby-store/src/test/java/org/apache/qpid/server/store/derby/DerbyMessageStoreTest.java +++ b/qpid/java/broker-plugins/derby-store/src/test/java/org/apache/qpid/server/store/derby/DerbyMessageStoreTest.java @@ -20,16 +20,17 @@ */ package org.apache.qpid.server.store.derby; +import static org.mockito.Mockito.when; + import java.io.File; +import java.util.HashMap; +import java.util.Map; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.MessageStoreTestCase; import org.apache.qpid.util.FileUtils; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.when; - public class DerbyMessageStoreTest extends MessageStoreTestCase { private String _storeLocation; @@ -63,7 +64,9 @@ public class DerbyMessageStoreTest extends MessageStoreTestCase protected void setUpStoreConfiguration(VirtualHost virtualHost) throws Exception { _storeLocation = TMP_FOLDER + File.separator + getTestName(); - when(virtualHost.getAttribute(eq(VirtualHost.STORE_PATH))).thenReturn(_storeLocation); + Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); + messageStoreSettings.put(MessageStore.STORE_PATH, _storeLocation); + when(virtualHost.getMessageStoreSettings()).thenReturn(messageStoreSettings); deleteStoreIfExists(); } diff --git a/qpid/java/broker-plugins/jdbc-provider-bone/src/main/java/org/apache/qpid/server/store/jdbc/bonecp/BoneCPConnectionProvider.java b/qpid/java/broker-plugins/jdbc-provider-bone/src/main/java/org/apache/qpid/server/store/jdbc/bonecp/BoneCPConnectionProvider.java index 1cde6f130d..2b45aad5e5 100644 --- a/qpid/java/broker-plugins/jdbc-provider-bone/src/main/java/org/apache/qpid/server/store/jdbc/bonecp/BoneCPConnectionProvider.java +++ b/qpid/java/broker-plugins/jdbc-provider-bone/src/main/java/org/apache/qpid/server/store/jdbc/bonecp/BoneCPConnectionProvider.java @@ -20,58 +20,38 @@ */ package org.apache.qpid.server.store.jdbc.bonecp; -import com.jolbox.bonecp.BoneCP; -import com.jolbox.bonecp.BoneCPConfig; import java.sql.Connection; import java.sql.SQLException; -import org.apache.commons.configuration.Configuration; -import org.apache.qpid.server.model.VirtualHost; +import java.util.Map; + import org.apache.qpid.server.store.jdbc.ConnectionProvider; +import org.apache.qpid.server.util.MapValueConverter; + +import com.jolbox.bonecp.BoneCP; +import com.jolbox.bonecp.BoneCPConfig; public class BoneCPConnectionProvider implements ConnectionProvider { + public static final String PARTITION_COUNT = "partitionCount"; + public static final String MAX_CONNECTIONS_PER_PARTITION = "maxConnectionsPerPartition"; + public static final String MIN_CONNECTIONS_PER_PARTITION = "minConnectionsPerPartition"; + public static final int DEFAULT_MIN_CONNECTIONS_PER_PARTITION = 5; public static final int DEFAULT_MAX_CONNECTIONS_PER_PARTITION = 10; public static final int DEFAULT_PARTITION_COUNT = 4; + private final BoneCP _connectionPool; - public BoneCPConnectionProvider(String connectionUrl, VirtualHost virtualHost) throws SQLException + public BoneCPConnectionProvider(String connectionUrl, Map<String, Object> storeSettings) throws SQLException { BoneCPConfig config = new BoneCPConfig(); config.setJdbcUrl(connectionUrl); - - - config.setMinConnectionsPerPartition(getIntegerAttribute(virtualHost, "minConnectionsPerPartition", DEFAULT_MIN_CONNECTIONS_PER_PARTITION)); - config.setMaxConnectionsPerPartition(getIntegerAttribute(virtualHost, "maxConnectionsPerPartition", DEFAULT_MAX_CONNECTIONS_PER_PARTITION)); - config.setPartitionCount(getIntegerAttribute(virtualHost, "partitionCount",DEFAULT_PARTITION_COUNT)); + config.setMinConnectionsPerPartition(MapValueConverter.getIntegerAttribute(MIN_CONNECTIONS_PER_PARTITION, storeSettings, DEFAULT_MIN_CONNECTIONS_PER_PARTITION)); + config.setMaxConnectionsPerPartition(MapValueConverter.getIntegerAttribute(MAX_CONNECTIONS_PER_PARTITION, storeSettings, DEFAULT_MAX_CONNECTIONS_PER_PARTITION)); + config.setPartitionCount(MapValueConverter.getIntegerAttribute(PARTITION_COUNT, storeSettings, DEFAULT_PARTITION_COUNT)); _connectionPool = new BoneCP(config); } - private int getIntegerAttribute(VirtualHost virtualHost, String attributeName, int defaultVal) - { - Object attrValue = virtualHost.getAttribute(attributeName); - if(attrValue != null) - { - if(attrValue instanceof Number) - { - return ((Number) attrValue).intValue(); - } - else if(attrValue instanceof String) - { - try - { - return Integer.parseInt((String)attrValue); - } - catch (NumberFormatException e) - { - return defaultVal; - } - } - - } - return defaultVal; - } - @Override public Connection getConnection() throws SQLException { diff --git a/qpid/java/broker-plugins/jdbc-provider-bone/src/main/java/org/apache/qpid/server/store/jdbc/bonecp/BoneCPConnectionProviderFactory.java b/qpid/java/broker-plugins/jdbc-provider-bone/src/main/java/org/apache/qpid/server/store/jdbc/bonecp/BoneCPConnectionProviderFactory.java index 73876eceb4..58206b270c 100644 --- a/qpid/java/broker-plugins/jdbc-provider-bone/src/main/java/org/apache/qpid/server/store/jdbc/bonecp/BoneCPConnectionProviderFactory.java +++ b/qpid/java/broker-plugins/jdbc-provider-bone/src/main/java/org/apache/qpid/server/store/jdbc/bonecp/BoneCPConnectionProviderFactory.java @@ -21,8 +21,8 @@ package org.apache.qpid.server.store.jdbc.bonecp; import java.sql.SQLException; -import org.apache.commons.configuration.Configuration; -import org.apache.qpid.server.model.VirtualHost; +import java.util.Map; + import org.apache.qpid.server.plugin.JDBCConnectionProviderFactory; import org.apache.qpid.server.store.jdbc.ConnectionProvider; @@ -35,9 +35,9 @@ public class BoneCPConnectionProviderFactory implements JDBCConnectionProviderFa } @Override - public ConnectionProvider getConnectionProvider(String connectionUrl, VirtualHost virtualHost) + public ConnectionProvider getConnectionProvider(String connectionUrl, Map<String, Object> storeSettings) throws SQLException { - return new BoneCPConnectionProvider(connectionUrl, virtualHost); + return new BoneCPConnectionProvider(connectionUrl, storeSettings); } } diff --git a/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/DefaultConnectionProviderFactory.java b/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/DefaultConnectionProviderFactory.java index 8fc7de12d0..191cc2ab7a 100644 --- a/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/DefaultConnectionProviderFactory.java +++ b/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/DefaultConnectionProviderFactory.java @@ -20,21 +20,23 @@ */ package org.apache.qpid.server.store.jdbc; -import org.apache.qpid.server.model.VirtualHost; +import java.util.Map; + import org.apache.qpid.server.plugin.JDBCConnectionProviderFactory; public class DefaultConnectionProviderFactory implements JDBCConnectionProviderFactory { + public static final String TYPE = "DEFAULT"; + @Override public String getType() { - return "NONE"; + return TYPE; } @Override - public ConnectionProvider getConnectionProvider(String connectionUrl, - VirtualHost virtualHost) + public ConnectionProvider getConnectionProvider(String connectionUrl, Map<String, Object> settings) { return new DefaultConnectionProvider(connectionUrl); } diff --git a/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStore.java b/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStore.java index 621759ef85..2c2b701c61 100644 --- a/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStore.java +++ b/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStore.java @@ -29,6 +29,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; + import org.apache.log4j.Logger; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.plugin.JDBCConnectionProviderFactory; @@ -37,6 +38,7 @@ import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.StoreException; import org.apache.qpid.server.store.StoreFuture; import org.apache.qpid.server.store.Transaction; +import org.apache.qpid.server.util.MapValueConverter; /** * An implementation of a {@link org.apache.qpid.server.store.MessageStore} that uses a JDBC database as the persistence @@ -48,10 +50,13 @@ public class JDBCMessageStore extends AbstractJDBCMessageStore implements Messag private static final Logger _logger = Logger.getLogger(JDBCMessageStore.class); - public static final String TYPE = "JDBC"; public static final String CONNECTION_URL = "connectionURL"; - public static final String CONFIG_CONNECTION_URL = "configConnectionURL"; + public static final String CONNECTION_POOL = "connectionPool"; + public static final String JDBC_BIG_INT_TYPE = "jdbcBigIntType"; + public static final String JDBC_BYTES_FOR_BLOB = "jdbcBytesForBlob"; + public static final String JDBC_VARBINARY_TYPE = "jdbcVarbinaryType"; + public static final String JDBC_BLOB_TYPE = "jdbcBlobType"; protected String _connectionURL; private ConnectionProvider _connectionProvider; @@ -280,21 +285,10 @@ public class JDBCMessageStore extends AbstractJDBCMessageStore implements Messag VirtualHost virtualHost) throws ClassNotFoundException, SQLException { + Map<String, Object> storeSettings = isConfigStoreOnly() ? virtualHost.getConfigurationStoreSettings() : virtualHost.getMessageStoreSettings(); + String connectionURL = String.valueOf(storeSettings.get(CONNECTION_URL)); + Object poolAttribute = storeSettings.get(CONNECTION_POOL); - String connectionURL; - if(!isConfigStoreOnly()) - { - connectionURL = virtualHost.getAttribute(CONNECTION_URL) == null - ? String.valueOf(virtualHost.getAttribute(VirtualHost.STORE_PATH)) - : String.valueOf(virtualHost.getAttribute(CONNECTION_URL)); - } - else - { - connectionURL = virtualHost.getAttribute(CONFIG_CONNECTION_URL) == null - ? String.valueOf(virtualHost.getAttribute(VirtualHost.CONFIG_STORE_PATH)) - : String.valueOf(virtualHost.getAttribute(CONFIG_CONNECTION_URL)); - - } JDBCDetails details = null; String[] components = connectionURL.split(":",3); @@ -312,9 +306,7 @@ public class JDBCMessageStore extends AbstractJDBCMessageStore implements Messag details = DERBY_DETAILS; } - - Object poolAttribute = virtualHost.getAttribute("connectionPool"); - String connectionPoolType = poolAttribute == null ? "DEFAULT" : String.valueOf(poolAttribute); + String connectionPoolType = poolAttribute == null ? DefaultConnectionProviderFactory.TYPE : String.valueOf(poolAttribute); JDBCConnectionProviderFactory connectionProviderFactory = JDBCConnectionProviderFactory.FACTORIES.get(connectionPoolType); @@ -324,44 +316,14 @@ public class JDBCMessageStore extends AbstractJDBCMessageStore implements Messag connectionProviderFactory = new DefaultConnectionProviderFactory(); } - _connectionProvider = connectionProviderFactory.getConnectionProvider(connectionURL, virtualHost); - - _blobType = getStringAttribute(virtualHost, "jdbcBlobType",details.getBlobType()); - _varBinaryType = getStringAttribute(virtualHost, "jdbcVarbinaryType",details.getVarBinaryType()); - _useBytesMethodsForBlob = getBooleanAttribute(virtualHost, "jdbcBytesForBlob",details.isUseBytesMethodsForBlob()); - _bigIntType = getStringAttribute(virtualHost, "jdbcBigIntType", details.getBigintType()); - } - - - private String getStringAttribute(VirtualHost virtualHost, String attributeName, String defaultVal) - { - Object attrValue = virtualHost.getAttribute(attributeName); - if(attrValue != null) - { - return attrValue.toString(); - } - return defaultVal; - } - - private boolean getBooleanAttribute(VirtualHost virtualHost, String attributeName, boolean defaultVal) - { - Object attrValue = virtualHost.getAttribute(attributeName); - if(attrValue != null) - { - if(attrValue instanceof Boolean) - { - return ((Boolean) attrValue).booleanValue(); - } - else if(attrValue instanceof String) - { - return Boolean.parseBoolean((String)attrValue); - } - - } - return defaultVal; + _connectionProvider = connectionProviderFactory.getConnectionProvider(connectionURL, storeSettings); + _blobType = MapValueConverter.getStringAttribute(JDBC_BLOB_TYPE, storeSettings, details.getBlobType()); + _varBinaryType = MapValueConverter.getStringAttribute(JDBC_VARBINARY_TYPE, storeSettings, details.getVarBinaryType()); + _useBytesMethodsForBlob = MapValueConverter.getBooleanAttribute(JDBC_BYTES_FOR_BLOB, storeSettings, details.isUseBytesMethodsForBlob()); + _bigIntType = MapValueConverter.getStringAttribute(JDBC_BIG_INT_TYPE, storeSettings, details.getBigintType()); } - + @Override protected void storedSizeChange(int contentSize) { } diff --git a/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStoreFactory.java b/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStoreFactory.java index 1144eaaf18..acce1b75a2 100644 --- a/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStoreFactory.java +++ b/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStoreFactory.java @@ -20,9 +20,8 @@ */ package org.apache.qpid.server.store.jdbc; -import java.util.HashMap; import java.util.Map; -import org.apache.commons.configuration.Configuration; + import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.plugin.DurableConfigurationStoreFactory; import org.apache.qpid.server.plugin.MessageStoreFactory; @@ -51,56 +50,30 @@ public class JDBCMessageStoreFactory implements MessageStoreFactory, DurableConf } @Override - public Map<String, Object> convertStoreConfiguration(Configuration storeConfiguration) - { - Map<String,Object> convertedMap = new HashMap<String,Object>(); - convertedMap.put("jdbcBlobType", storeConfiguration.getString("sqlBlobType")); - convertedMap.put("jdbcVarbinaryType", storeConfiguration.getString("sqlVarbinaryType")); - if(storeConfiguration.containsKey("useBytesForBlob")) - { - convertedMap.put("jdbcUseBytesForBlob", storeConfiguration.getBoolean("useBytesForBlob")); - } - convertedMap.put("jdbcBigIntType", storeConfiguration.getString("sqlBigIntType")); - convertedMap.put("connectionPool", storeConfiguration.getString("pool.type")); - convertedMap.put("minConnectionsPerPartition", storeConfiguration.getInteger("pool.minConnectionsPerPartition", - null)); - convertedMap.put("maxConnectionsPerPartition", storeConfiguration.getInteger("pool.maxConnectionsPerPartition", - null)); - convertedMap.put("partitionCount", storeConfiguration.getInteger("pool.partitionCount", null)); - - return convertedMap; - } - - - @Override public void validateAttributes(Map<String, Object> attributes) { - if(getType().equals(attributes.get(VirtualHost.STORE_TYPE))) + @SuppressWarnings("unchecked") + Map<String, Object> messageStoreSettings = (Map<String, Object>) attributes.get(VirtualHost.MESSAGE_STORE_SETTINGS); + if(getType().equals(messageStoreSettings.get(MessageStore.STORE_TYPE))) { - Object connectionURL = attributes.get(JDBCMessageStore.CONNECTION_URL); + Object connectionURL = messageStoreSettings.get(JDBCMessageStore.CONNECTION_URL); if(!(connectionURL instanceof String)) { - Object storePath = attributes.get(VirtualHost.STORE_PATH); - if(!(storePath instanceof String)) - { - throw new IllegalArgumentException("Attribute '"+ JDBCMessageStore.CONNECTION_URL - +"' is required and must be of type String."); + throw new IllegalArgumentException("Setting '"+ JDBCMessageStore.CONNECTION_URL + +"' is required and must be of type String."); - } } } - if(getType().equals(attributes.get(VirtualHost.CONFIG_STORE_TYPE))) + + @SuppressWarnings("unchecked") + Map<String, Object> configurationStoreSettings = (Map<String, Object>) attributes.get(VirtualHost.CONFIGURATION_STORE_SETTINGS); + if(configurationStoreSettings != null && getType().equals(configurationStoreSettings.get(DurableConfigurationStore.STORE_TYPE))) { - Object connectionURL = attributes.get(JDBCMessageStore.CONFIG_CONNECTION_URL); + Object connectionURL = configurationStoreSettings.get(JDBCMessageStore.CONNECTION_URL); if(!(connectionURL instanceof String)) { - Object storePath = attributes.get(VirtualHost.CONFIG_STORE_PATH); - if(!(storePath instanceof String)) - { - throw new IllegalArgumentException("Attribute '"+ JDBCMessageStore.CONFIG_CONNECTION_URL - +"' is required and must be of type String."); - - } + throw new IllegalArgumentException("Setting '"+ JDBCMessageStore.CONNECTION_URL + +"' is required and must be of type String."); } } } diff --git a/qpid/java/broker-core/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.JDBCConnectionProviderFactory b/qpid/java/broker-plugins/jdbc-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.JDBCConnectionProviderFactory index e0ae6e97cc..e0ae6e97cc 100644 --- a/qpid/java/broker-core/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.JDBCConnectionProviderFactory +++ b/qpid/java/broker-plugins/jdbc-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.JDBCConnectionProviderFactory diff --git a/qpid/java/broker-plugins/jdbc-store/src/test/java/org/apache/qpid/server/store/jdbc/JDBCMessageStoreTest.java b/qpid/java/broker-plugins/jdbc-store/src/test/java/org/apache/qpid/server/store/jdbc/JDBCMessageStoreTest.java index 9c348383c6..dc6bb0158d 100644 --- a/qpid/java/broker-plugins/jdbc-store/src/test/java/org/apache/qpid/server/store/jdbc/JDBCMessageStoreTest.java +++ b/qpid/java/broker-plugins/jdbc-store/src/test/java/org/apache/qpid/server/store/jdbc/JDBCMessageStoreTest.java @@ -20,21 +20,22 @@ */ package org.apache.qpid.server.store.jdbc; +import static org.mockito.Mockito.when; + import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.MessageStoreTestCase; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.when; - public class JDBCMessageStoreTest extends MessageStoreTestCase { private String _connectionURL; @@ -66,10 +67,12 @@ public class JDBCMessageStoreTest extends MessageStoreTestCase protected void setUpStoreConfiguration(VirtualHost virtualHost) throws Exception { _connectionURL = "jdbc:derby:memory:/" + getTestName() + ";create=true"; - - when(virtualHost.getAttribute(eq("connectionURL"))).thenReturn(_connectionURL); + Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); + messageStoreSettings.put(JDBCMessageStore.CONNECTION_URL, _connectionURL); + when(virtualHost.getMessageStoreSettings()).thenReturn(messageStoreSettings); } + @Override protected MessageStore createMessageStore() { diff --git a/qpid/java/broker-plugins/management-jmx/pom.xml b/qpid/java/broker-plugins/management-jmx/pom.xml index 0f04f393c5..c253b4d75d 100644 --- a/qpid/java/broker-plugins/management-jmx/pom.xml +++ b/qpid/java/broker-plugins/management-jmx/pom.xml @@ -55,6 +55,13 @@ <version>${project.version}</version> <scope>test</scope> </dependency> + + <dependency> + <groupId>commons-beanutils</groupId> + <artifactId>commons-beanutils-core</artifactId> + <scope>test</scope> + </dependency> + </dependencies> <build> diff --git a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObjectRegistry.java b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObjectRegistry.java index d8aea03b36..26608d4309 100644 --- a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObjectRegistry.java +++ b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObjectRegistry.java @@ -20,10 +20,10 @@ */ package org.apache.qpid.server.jmx; -import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.common.Closeable; import javax.management.JMException; + import java.io.IOException; /** @@ -40,7 +40,7 @@ import java.io.IOException; */ public interface ManagedObjectRegistry extends Closeable { - void start() throws IOException, ConfigurationException; + void start() throws IOException; void registerObject(ManagedObject managedObject) throws JMException; diff --git a/qpid/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java b/qpid/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java index 49f823e7ee..db4cae1258 100644 --- a/qpid/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java +++ b/qpid/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java @@ -20,9 +20,8 @@ */ package org.apache.qpid.server.store; -import java.util.Collections; import java.util.Map; -import org.apache.commons.configuration.Configuration; + import org.apache.qpid.server.plugin.MessageStoreFactory; public class MemoryMessageStoreFactory implements MessageStoreFactory @@ -41,12 +40,6 @@ public class MemoryMessageStoreFactory implements MessageStoreFactory } @Override - public Map<String, Object> convertStoreConfiguration(Configuration configuration) - { - return Collections.emptyMap(); - } - - @Override public void validateAttributes(Map<String, Object> attributes) { } diff --git a/qpid/java/build.deps b/qpid/java/build.deps index 0aa35954bf..f4496ce8ab 100644 --- a/qpid/java/build.deps +++ b/qpid/java/build.deps @@ -21,8 +21,6 @@ commons-beanutils-core=lib/required/commons-beanutils-core-1.8.3.jar commons-cli=lib/required/commons-cli-1.2.jar commons-codec=lib/required/commons-codec-1.6.jar commons-collections=lib/required/commons-collections-3.2.1.jar -commons-configuration=lib/required/commons-configuration-1.8.jar -commons-digester=lib/required/commons-digester-1.8.1.jar commons-lang=lib/required/commons-lang-2.6.jar commons-logging=lib/required/commons-logging-1.1.1.jar @@ -65,8 +63,7 @@ dojo=lib/required/dojo-${dojo-version}.zip jackson-core=lib/required/jackson-core-asl-1.9.0.jar jackson-mapper=lib/required/jackson-mapper-asl-1.9.0.jar -commons-configuration.libs = ${commons-beanutils-core} ${commons-digester} \ - ${commons-codec} ${commons-lang} ${commons-collections} ${commons-configuration} +commons.libs = ${commons-codec} ${commons-lang} common.libs=${slf4j-api} client.libs=${geronimo-jms} @@ -75,20 +72,20 @@ amqp-1-0-client.libs= amqp-1-0-client-example.libs=${commons-cli} amqp-1-0-client-jms.libs=${geronimo-jms} amqp-1-0-client-websocket.libs = ${jetty} ${jetty-continuation} ${jetty-security} ${jetty-http} ${jetty-io} ${jetty-servlet} ${jetty-util} ${servlet-api} ${jetty-websocket} -tools.libs=${commons-configuration.libs} ${log4j} +tools.libs=${commons.libs} ${log4j} broker-core.libs=${commons-cli} ${commons-logging} ${log4j} ${slf4j-log4j} \ - ${xalan} ${derby-db} ${commons-configuration.libs} \ + ${xalan} ${derby-db} ${commons.libs} \ ${jackson-core} ${jackson-mapper} ${jetty} ${jetty-continuation} ${jetty-security} ${jetty-http} ${jetty-io} ${jetty-servlet} ${jetty-util} ${servlet-api} ${jetty-websocket} ${bcel} #Borrow the broker-core libs, hack for release binary generation broker.libs=${broker-core.libs} broker-plugins-management-http.libs=${dojo} -broker-plugins.libs=${log4j} ${commons-configuration.libs} +broker-plugins.libs=${log4j} ${commons.libs} test.libs=${slf4j-log4j} ${log4j} ${junit} ${slf4j-api} ${mockito-all} -perftests.libs=${geronimo-jms} ${slf4j-api} ${log4j} ${slf4j-log4j} ${commons-logging} ${commons-collections} ${commons-beanutils-core} ${commons-lang} ${gson-all} ${derby-db} +perftests.libs=${geronimo-jms} ${slf4j-api} ${log4j} ${slf4j-log4j} ${commons-logging} ${commons-beanutils-core} ${commons-lang} ${commons-collections} ${gson-all} ${derby-db} management-common.libs= @@ -105,7 +102,7 @@ qpid-test-utils.libs = ${test.libs} ${geronimo-jms} broker-plugins-access-control.test.libs=${test.libs} broker-plugins-management-amqp.test.libs=${test.libs} broker-plugins-management-http.test.libs=${test.libs} -broker-plugins-management-jmx.test.libs=${test.libs} +broker-plugins-management-jmx.test.libs=${commons-beanutils-core} ${test.libs} broker-plugins-jdbc-store.test.libs=${test.libs} broker-plugins-derby-store.test.libs=${test.libs} broker-plugins-memory-store.test.libs=${test.libs} diff --git a/qpid/java/ivy.retrieve.xml b/qpid/java/ivy.retrieve.xml index 59b3fa70af..dcb97fcf9f 100644 --- a/qpid/java/ivy.retrieve.xml +++ b/qpid/java/ivy.retrieve.xml @@ -38,8 +38,6 @@ <dependency org="commons-cli" name="commons-cli" rev="1.2" transitive="false"/> <dependency org="commons-codec" name="commons-codec" rev="1.6" transitive="false"/> <dependency org="commons-collections" name="commons-collections" rev="3.2.1" transitive="false"/> - <dependency org="commons-configuration" name="commons-configuration" rev="1.8" transitive="false"/> - <dependency org="commons-digester" name="commons-digester" rev="1.8.1" transitive="false"/> <dependency org="commons-lang" name="commons-lang" rev="2.6" transitive="false"/> <dependency org="commons-logging" name="commons-logging" rev="1.1.1" transitive="false"/> <dependency org="org.apache.bcel" name="bcel" rev="5.2" transitive="false"/> diff --git a/qpid/java/lib/poms/commons-configuration-1.8.xml b/qpid/java/lib/poms/commons-configuration-1.8.xml deleted file mode 100644 index 337b9d0993..0000000000 --- a/qpid/java/lib/poms/commons-configuration-1.8.xml +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0"?> -<!-- - 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. ---> -<dep> - <groupId>commons-configuration</groupId> - <artifactId>commons-configuration</artifactId> - <version>1.8</version> -</dep> diff --git a/qpid/java/lib/poms/commons-digester-1.8.1.xml b/qpid/java/lib/poms/commons-digester-1.8.1.xml deleted file mode 100644 index 56b38bf778..0000000000 --- a/qpid/java/lib/poms/commons-digester-1.8.1.xml +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0"?> -<!-- - 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. ---> -<dep> - <groupId>commons-digester</groupId> - <artifactId>commons-digester</artifactId> - <version>1.8.1</version> - <exclusions> - <exclusion> - <groupId>commons-beanutils</groupId> - <artifactId>commons-beanutils</artifactId> - </exclusion> - </exclusions> -</dep> diff --git a/qpid/java/module.xml b/qpid/java/module.xml index 6d3f08a386..d598517a95 100644 --- a/qpid/java/module.xml +++ b/qpid/java/module.xml @@ -418,6 +418,7 @@ <propertyref name="java.naming.factory.initial"/> <propertyref name="java.naming.provider.url"/> <propertyref name="messagestore.class.name" /> + <propertyref name="messagestore.type" /> <propertyref name="max_prefetch"/> <propertyref name="QPID_HOME"/> diff --git a/qpid/java/pom.xml b/qpid/java/pom.xml index 74042dd0bc..e4b02850e5 100644 --- a/qpid/java/pom.xml +++ b/qpid/java/pom.xml @@ -70,7 +70,7 @@ <profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0</profile.qpid.broker_default_amqp_protocol_excludes> <profile.broker.virtualhosts-config>${QPID_HOME}${file.separator}etc${file.separator}virtualhosts-systests.xml</profile.broker.virtualhosts-config> <profile.broker.persistent>false</profile.broker.persistent> - <profile.messagestore.class.name>org.apache.qpid.server.store.MemoryMessageStore</profile.messagestore.class.name> + <profile.messagestore.type>Memory</profile.messagestore.type> </properties> <modules> @@ -152,7 +152,7 @@ <echo>[profile.qpid.broker_default_amqp_protocol_excludes] ${profile.qpid.broker_default_amqp_protocol_excludes}</echo> <echo>[profile.broker.virtualhosts-config] ${profile.broker.virtualhosts-config}</echo> <echo>[profile.broker.persistent] ${profile.broker.persistent}</echo> - <echo>[profile.messagestore.class.name] ${profile.messagestore.class.name}</echo> + <echo>[profile.messagestore.type] ${profile.messagestore.type}</echo> </tasks> </configuration> </execution> @@ -231,7 +231,7 @@ <qpid.broker_default_amqp_protocol_excludes>${profile.qpid.broker_default_amqp_protocol_excludes}</qpid.broker_default_amqp_protocol_excludes> <broker.virtualhosts-config>${profile.broker.virtualhosts-config}</broker.virtualhosts-config> <broker.persistent>${profile.broker.persistent}</broker.persistent> - <messagestore.class.name>${profile.messagestore.class.name}</messagestore.class.name> + <messagestore.type>${profile.messagestore.type}</messagestore.type> <profile>${profile}</profile> <!-- This must be a child of qpid home currently due to the horrible mechanics of QBTC --> @@ -424,7 +424,7 @@ <profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0</profile.qpid.broker_default_amqp_protocol_excludes> <profile.broker.virtualhosts-config>${QPID_HOME}${file.separator}etc${file.separator}virtualhosts-systests.xml</profile.broker.virtualhosts-config> <profile.broker.persistent>false</profile.broker.persistent> - <profile.messagestore.class.name>org.apache.qpid.server.store.MemoryMessageStore</profile.messagestore.class.name> + <profile.messagestore.type>Memory</profile.messagestore.type> </properties> </profile> @@ -443,7 +443,7 @@ <profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0,AMQP_0_10</profile.qpid.broker_default_amqp_protocol_excludes> <profile.broker.virtualhosts-config>${QPID_HOME}${file.separator}etc${file.separator}virtualhosts-systests.xml</profile.broker.virtualhosts-config> <profile.broker.persistent>false</profile.broker.persistent> - <profile.messagestore.class.name>org.apache.qpid.server.store.MemoryMessageStore</profile.messagestore.class.name> + <profile.messagestore.type>Memory</profile.messagestore.type> </properties> </profile> @@ -462,7 +462,7 @@ <profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0,AMQP_0_10,AMQP_0_9_1</profile.qpid.broker_default_amqp_protocol_excludes> <profile.broker.virtualhosts-config>${QPID_HOME}${file.separator}etc${file.separator}virtualhosts-systests.xml</profile.broker.virtualhosts-config> <profile.broker.persistent>false</profile.broker.persistent> - <profile.messagestore.class.name>org.apache.qpid.server.store.MemoryMessageStore</profile.messagestore.class.name> + <profile.messagestore.type>Memory</profile.messagestore.type> </properties> </profile> @@ -481,7 +481,7 @@ <profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0</profile.qpid.broker_default_amqp_protocol_excludes> <profile.broker.virtualhosts-config>${QPID_HOME}${file.separator}etc${file.separator}virtualhosts-systests-bdb.xml</profile.broker.virtualhosts-config> <profile.broker.persistent>true</profile.broker.persistent> - <profile.messagestore.class.name>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</profile.messagestore.class.name> + <profile.messagestore.type>BDB</profile.messagestore.type> </properties> </profile> @@ -500,7 +500,7 @@ <profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0,AMQP_0_10</profile.qpid.broker_default_amqp_protocol_excludes> <profile.broker.virtualhosts-config>${QPID_HOME}${file.separator}etc${file.separator}virtualhosts-systests-bdb.xml</profile.broker.virtualhosts-config> <profile.broker.persistent>true</profile.broker.persistent> - <profile.messagestore.class.name>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</profile.messagestore.class.name> + <profile.messagestore.type>BDB</profile.messagestore.type> </properties> </profile> @@ -519,7 +519,7 @@ <profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0,AMQP_0_10,AMQP_0_9_1</profile.qpid.broker_default_amqp_protocol_excludes> <profile.broker.virtualhosts-config>${QPID_HOME}${file.separator}etc${file.separator}virtualhosts-systests-bdb.xml</profile.broker.virtualhosts-config> <profile.broker.persistent>true</profile.broker.persistent> - <profile.messagestore.class.name>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</profile.messagestore.class.name> + <profile.messagestore.type>BDB</profile.messagestore.type> </properties> </profile> @@ -538,7 +538,7 @@ <profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0</profile.qpid.broker_default_amqp_protocol_excludes> <profile.broker.virtualhosts-config>${QPID_HOME}${file.separator}etc${file.separator}virtualhosts-systests-derby-mem.xml</profile.broker.virtualhosts-config> <profile.broker.persistent>true</profile.broker.persistent> - <profile.messagestore.class.name>org.apache.qpid.server.store.derby.DerbyMessageStore</profile.messagestore.class.name> + <profile.messagestore.type>DERBY</profile.messagestore.type> </properties> </profile> @@ -557,7 +557,7 @@ <profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0,AMQP_0_10</profile.qpid.broker_default_amqp_protocol_excludes> <profile.broker.virtualhosts-config>${QPID_HOME}${file.separator}etc${file.separator}virtualhosts-systests-derby-mem.xml</profile.broker.virtualhosts-config> <profile.broker.persistent>true</profile.broker.persistent> - <profile.messagestore.class.name>org.apache.qpid.server.store.derby.DerbyMessageStore</profile.messagestore.class.name> + <profile.messagestore.type>DERBY</profile.messagestore.type> </properties> </profile> @@ -576,7 +576,7 @@ <profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0,AMQP_0_10,AMQP_0_9_1</profile.qpid.broker_default_amqp_protocol_excludes> <profile.broker.virtualhosts-config>${QPID_HOME}${file.separator}etc${file.separator}virtualhosts-systests-derby-mem.xml</profile.broker.virtualhosts-config> <profile.broker.persistent>true</profile.broker.persistent> - <profile.messagestore.class.name>org.apache.qpid.server.store.derby.DerbyMessageStore</profile.messagestore.class.name> + <profile.messagestore.type>DERBY</profile.messagestore.type> </properties> </profile> diff --git a/qpid/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java b/qpid/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java index 20d5dd5453..7113f79829 100644 --- a/qpid/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java +++ b/qpid/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java @@ -22,6 +22,7 @@ package org.apache.qpid.test.utils; import junit.framework.TestCase; import junit.framework.TestResult; + import org.apache.log4j.Level; import org.apache.log4j.Logger; @@ -124,10 +125,7 @@ public class QpidTestCase extends TestCase } } - protected static final String MESSAGE_STORE_CLASS_NAME_KEY = "messagestore.class.name"; - protected static final String CONFIGURATION_STORE_CLASS_NAME_KEY = "configurationstore.class.name"; - - protected static final String MEMORY_STORE_CLASS_NAME = "org.apache.qpid.server.store.MemoryMessageStore"; + protected static final String MESSAGE_STORE_TYPE = "messagestore.type"; private static List<String> _exclusionList; @@ -151,12 +149,12 @@ public class QpidTestCase extends TestCase } } - public String getTestProfileMessageStoreClassName() + public String getTestProfileMessageStoreType() { - final String storeClass = System.getProperty(MESSAGE_STORE_CLASS_NAME_KEY); - _logger.debug("MESSAGE_STORE_CLASS_NAME_KEY " + storeClass); + final String storeType = System.getProperty(MESSAGE_STORE_TYPE); + _logger.debug(MESSAGE_STORE_TYPE + "=" + storeType); - return storeClass != null ? storeClass : MEMORY_STORE_CLASS_NAME ; + return storeType != null ? storeType : "TestableMemory"; } diff --git a/qpid/java/systests/etc/config-systests.json b/qpid/java/systests/etc/config-systests.json index 12a8a5c5a6..dac8ee4fd4 100644 --- a/qpid/java/systests/etc/config-systests.json +++ b/qpid/java/systests/etc/config-systests.json @@ -22,7 +22,7 @@ "name": "Broker", "defaultVirtualHost" : "test", "storeVersion": 1, - "modelVersion": "1.0", + "modelVersion": "1.4", "authenticationproviders" : [ { "name" : "plain", "type" : "PlainPasswordFile", @@ -59,6 +59,10 @@ }], "virtualhosts" : [ { "name" : "test", - "configPath" : "${broker.virtualhosts-config}" + "type" : "STANDARD", + "messageStoreSettings": { + "storeType": "${messagestore.type}", + "storePath" : "${QPID_WORK}/test/${test.port}" + } } ] } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java index a19ba21c5c..7d5690b1bd 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java @@ -25,9 +25,17 @@ import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE_PASSWORD; import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE; import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE_PASSWORD; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; import java.util.Arrays; -import javax.net.ssl.SSLSocket; -import org.apache.commons.configuration.ConfigurationException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import javax.jms.Connection; +import javax.jms.JMSException; +import javax.jms.Session; + import org.apache.qpid.client.AMQConnectionURL; import org.apache.qpid.client.AMQTestConnection_0_10; import org.apache.qpid.jms.ConnectionURL; @@ -36,15 +44,6 @@ import org.apache.qpid.server.model.Transport; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.test.utils.TestBrokerConfiguration; -import javax.jms.Connection; -import javax.jms.JMSException; -import javax.jms.Session; -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - public class SSLTest extends QpidBrokerTestCase { private static final String CERT_ALIAS_APP1 = "app1"; @@ -402,7 +401,7 @@ public class SSLTest extends QpidBrokerTestCase boolean sslOnly, boolean needClientAuth, boolean wantClientAuth, - boolean samePort) throws ConfigurationException + boolean samePort) throws Exception { if(isJavaBroker()) { diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java index 68ec101245..d3d952ea8c 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java @@ -20,8 +20,19 @@ */ package org.apache.qpid.server.logging; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + import org.apache.qpid.client.AMQDestination; import org.apache.qpid.client.AMQSession; +import org.apache.qpid.server.management.plugin.HttpManagement; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManagerFactory; +import org.apache.qpid.systest.rest.RestTestHelper; +import org.apache.qpid.test.utils.TestBrokerConfiguration; import javax.jms.Connection; import javax.jms.Queue; @@ -29,7 +40,7 @@ import javax.jms.Session; public class AlertingTest extends AbstractTestLogging { - private String VIRTUALHOST = "test"; + private Session _session; private Connection _connection; private Queue _destination; @@ -41,9 +52,9 @@ public class AlertingTest extends AbstractTestLogging public void setUp() throws Exception { _numMessages = 50; - - setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.checkPeriod", String.valueOf(ALERT_LOG_WAIT_PERIOD)); - setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".queues.maximumMessageCount", String.valueOf(_numMessages)); + TestBrokerConfiguration brokerConfiguration = getBrokerConfiguration(); + brokerConfiguration.setBrokerAttribute(Broker.VIRTUALHOST_HOUSEKEEPING_CHECK_PERIOD, String.valueOf(ALERT_LOG_WAIT_PERIOD)); + brokerConfiguration.setBrokerAttribute(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, _numMessages); // Then we do the normal setup stuff like starting the broker, getting a connection etc. super.setUp(); @@ -140,8 +151,24 @@ public class AlertingTest extends AbstractTestLogging _monitor.markDiscardPoint(); - // Change max message count to 5, start broker and make sure that that's triggered at the right time - setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".queues.maximumMessageCount", "5"); + RestTestHelper restTestHelper = new RestTestHelper(findFreePort()); + TestBrokerConfiguration config = getBrokerConfiguration(); + config.addHttpManagementConfiguration(); + config.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT, Port.PORT, restTestHelper.getHttpPort()); + config.removeObjectConfiguration(TestBrokerConfiguration.ENTRY_NAME_JMX_PORT); + config.removeObjectConfiguration(TestBrokerConfiguration.ENTRY_NAME_RMI_PORT); + + Map<String, Object> anonymousProviderAttributes = new HashMap<String, Object>(); + anonymousProviderAttributes.put(AuthenticationProvider.TYPE, AnonymousAuthenticationManagerFactory.PROVIDER_TYPE); + anonymousProviderAttributes.put(AuthenticationProvider.NAME, "testAnonymous"); + config.addAuthenticationProviderConfiguration(anonymousProviderAttributes); + + // set password authentication provider on http port for the tests + config.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT, Port.AUTHENTICATION_PROVIDER, + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER); + config.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_MANAGEMENT, HttpManagement.HTTP_BASIC_AUTHENTICATION_ENABLED, true); + config.setSaved(false); + restTestHelper.setUsernameAndPassword("webadmin", "webadmin"); startBroker(); @@ -154,6 +181,12 @@ public class AlertingTest extends AbstractTestLogging // Ensure the alert has not occurred yet assertLoggingNotYetOccured(MESSAGE_COUNT_ALERT); + // Change max message count to 5, start broker and make sure that that's triggered at the right time + TestBrokerConfiguration brokerConfiguration = getBrokerConfiguration(); + brokerConfiguration.setBrokerAttribute(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 5); + brokerConfiguration.setSaved(false); + + restTestHelper.submitRequest("/rest/queue/test/" + getTestQueueName(), "PUT", Collections.<String, Object>singletonMap(org.apache.qpid.server.model.Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 5)); // Trigger the new value sendMessage(_session, _destination, 3); _session.commit(); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java index 7a3edd316f..72626e5089 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java @@ -18,22 +18,22 @@ */ package org.apache.qpid.server.security.acl; -import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.lang.StringUtils; - import org.apache.qpid.AMQException; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQConnectionURL; import org.apache.qpid.jms.ConnectionListener; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.test.utils.TestBrokerConfiguration; import org.apache.qpid.url.URLSyntaxException; import javax.jms.Connection; import javax.jms.ExceptionListener; import javax.jms.JMSException; import javax.naming.NamingException; + import java.io.File; import java.io.FileWriter; import java.io.IOException; @@ -98,23 +98,24 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements } } - public void writeACLFile(final String vhost, final String...rules) throws ConfigurationException, IOException + public void writeACLFile(final String vhost, final String...rules) throws IOException { writeACLFileUtil(this, vhost, rules); } - public static void writeACLFileUtil(QpidBrokerTestCase testcase, String vhost, String...rules) throws ConfigurationException, IOException + public static void writeACLFileUtil(QpidBrokerTestCase testcase, String vhost, String...rules) throws IOException { File aclFile = File.createTempFile(testcase.getClass().getSimpleName(), testcase.getName()); aclFile.deleteOnExit(); + TestBrokerConfiguration config = testcase.getBrokerConfiguration(); if (vhost == null) { - testcase.getBrokerConfiguration().addAclFileConfiguration(aclFile.getAbsolutePath()); + config.addAclFileConfiguration(aclFile.getAbsolutePath()); } else { - testcase.setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + vhost + ".security.acl", aclFile.getAbsolutePath()); + config.setObjectAttribute(vhost, VirtualHost.SECURITY_ACL, aclFile.getAbsolutePath()); } PrintWriter out = new PrintWriter(new FileWriter(aclFile)); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java index e076415146..85d3fc0cdc 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java @@ -38,7 +38,6 @@ import java.util.Map; import javax.jms.Connection; import javax.jms.JMSException; -import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.client.AMQConnectionURL; import org.apache.qpid.management.common.mbeans.ManagedConnection; import org.apache.qpid.server.model.AuthenticationProvider; @@ -328,12 +327,12 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase return getConnection(new AMQConnectionURL(url)); } - private void setCommonBrokerSSLProperties(boolean needClientAuth) throws ConfigurationException + private void setCommonBrokerSSLProperties(boolean needClientAuth) { setCommonBrokerSSLProperties(needClientAuth, Collections.singleton(TestBrokerConfiguration.ENTRY_NAME_SSL_TRUSTSTORE)); } - private void setCommonBrokerSSLProperties(boolean needClientAuth, Collection<String> trustStoreNames) throws ConfigurationException + private void setCommonBrokerSSLProperties(boolean needClientAuth, Collection<String> trustStoreNames) { TestBrokerConfiguration config = getBrokerConfiguration(); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/MessageStoreTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/MessageStoreTest.java index 1d7c2ffa46..36e86fbe7b 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/MessageStoreTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/MessageStoreTest.java @@ -21,10 +21,15 @@ package org.apache.qpid.server.store; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; import java.util.ArrayList; import java.util.Collection; - -import org.apache.commons.configuration.PropertiesConfiguration; +import java.util.HashMap; +import java.util.Map; import org.apache.log4j.Logger; import org.apache.qpid.common.AMQPFilterTypes; @@ -34,41 +39,34 @@ import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.framing.amqp_8_0.BasicConsumeBodyImpl; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.exchange.DirectExchange; import org.apache.qpid.server.exchange.ExchangeImpl; import org.apache.qpid.server.exchange.TopicExchange; +import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.message.InstanceProperties; import org.apache.qpid.server.message.MessageSource; import org.apache.qpid.server.model.Binding; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ExclusivityPolicy; import org.apache.qpid.server.model.LifetimePolicy; import org.apache.qpid.server.model.Queue; -import org.apache.qpid.server.protocol.v0_8.AMQMessage; -import org.apache.qpid.server.protocol.v0_8.MessageMetaData; -import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.plugin.ExchangeType; -import org.apache.qpid.server.queue.PriorityQueue; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; +import org.apache.qpid.server.protocol.v0_8.MessageMetaData; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.ConflationQueue; +import org.apache.qpid.server.queue.PriorityQueue; import org.apache.qpid.server.queue.StandardQueue; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.server.virtualhost.StandardVirtualHostFactory; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; import org.apache.qpid.test.utils.QpidTestCase; import org.apache.qpid.util.FileUtils; -import java.io.File; -import java.util.HashMap; -import java.util.Map; - -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - /** * This tests the MessageStores by using the available interfaces. * @@ -104,8 +102,6 @@ public class MessageStoreTest extends QpidTestCase private String queueOwner = "MST"; - private PropertiesConfiguration _config; - private VirtualHost _virtualHost; private org.apache.qpid.server.model.VirtualHost _virtualHostModel; private Broker _broker; @@ -116,15 +112,19 @@ public class MessageStoreTest extends QpidTestCase super.setUp(); BrokerTestHelper.setUp(); - _storePath = System.getProperty("QPID_WORK") + File.separator + getName(); - - _config = new PropertiesConfiguration(); - _config.addProperty("store.class", getTestProfileMessageStoreClassName()); - _config.addProperty("store.environment-path", _storePath); - _virtualHostModel = mock(org.apache.qpid.server.model.VirtualHost.class); - when(_virtualHostModel.getAttribute(eq(org.apache.qpid.server.model.VirtualHost.STORE_PATH))).thenReturn(_storePath); + String hostName = getName(); + _storePath = System.getProperty("QPID_WORK", TMP_FOLDER + File.separator + getTestName()) + File.separator + hostName; + Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); + messageStoreSettings.put(MessageStore.STORE_PATH, _storePath); + messageStoreSettings.put(MessageStore.STORE_TYPE, getTestProfileMessageStoreType()); + _virtualHostModel = mock(org.apache.qpid.server.model.VirtualHost.class); + when(_virtualHostModel.getMessageStoreSettings()).thenReturn(messageStoreSettings); + when(_virtualHostModel.getAttribute(eq(org.apache.qpid.server.model.VirtualHost.TYPE))).thenReturn(StandardVirtualHostFactory.TYPE); + when(_virtualHostModel.getAttribute(eq(org.apache.qpid.server.model.VirtualHost.NAME))).thenReturn(hostName); + when(_virtualHostModel.getType()).thenReturn(StandardVirtualHostFactory.TYPE); + when(_virtualHostModel.getName()).thenReturn(hostName); cleanup(new File(_storePath)); @@ -138,7 +138,7 @@ public class MessageStoreTest extends QpidTestCase return _storePath; } - protected org.apache.qpid.server.model.VirtualHost getVirtualHostModel() + protected org.apache.qpid.server.model.VirtualHost<?> getVirtualHostModel() { return _virtualHostModel; } @@ -165,11 +165,6 @@ public class MessageStoreTest extends QpidTestCase return _virtualHost; } - public PropertiesConfiguration getConfig() - { - return _config; - } - protected void reloadVirtualHost() { VirtualHost original = getVirtualHost(); @@ -189,7 +184,7 @@ public class MessageStoreTest extends QpidTestCase try { - _virtualHost = BrokerTestHelper.createVirtualHost(new VirtualHostConfiguration(getClass().getName(), _config, _broker),new VirtualHostRegistry(_broker.getEventLogger()),getVirtualHostModel()); + _virtualHost = BrokerTestHelper.createVirtualHost(new VirtualHostRegistry(new EventLogger()), getVirtualHostModel()); } catch (Exception e) { diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java index 19e258d060..7017ea6d45 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.server.store; +import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; @@ -30,6 +31,7 @@ import org.apache.qpid.server.model.VirtualHost; public class QuotaMessageStore extends NullMessageStore { + public static final String TYPE = "QuotaMessageStore"; private final AtomicLong _messageId = new AtomicLong(1); private final AtomicBoolean _closed = new AtomicBoolean(false); @@ -49,14 +51,15 @@ public class @Override public void configureConfigStore(VirtualHost virtualHost, ConfigurationRecoveryHandler recoveryHandler) { - Object overfullAttr = virtualHost.getAttribute(MessageStoreConstants.OVERFULL_SIZE_ATTRIBUTE); + Map<String, Object> messageStoreSettings = virtualHost.getMessageStoreSettings(); + Object overfullAttr = messageStoreSettings.get(MessageStore.OVERFULL_SIZE); _persistentSizeHighThreshold = overfullAttr == null ? Long.MAX_VALUE : overfullAttr instanceof Number ? ((Number)overfullAttr).longValue() : Long.parseLong(overfullAttr.toString()); - Object underfullAttr = virtualHost.getAttribute(MessageStoreConstants.UNDERFULL_SIZE_ATTRIBUTE); + Object underfullAttr = messageStoreSettings.get(MessageStore.UNDERFULL_SIZE); _persistentSizeLowThreshold = overfullAttr == null ? _persistentSizeHighThreshold diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/MessageStoreConstants.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStoreFactory.java index 93b669e6e4..b4f81e2ad6 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/MessageStoreConstants.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStoreFactory.java @@ -1,4 +1,5 @@ /* + * * 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 @@ -17,15 +18,31 @@ * under the License. * */ + package org.apache.qpid.server.store; -public class MessageStoreConstants +import java.util.Map; + +import org.apache.qpid.server.plugin.MessageStoreFactory; + +public class QuotaMessageStoreFactory implements MessageStoreFactory { - public static final String ENVIRONMENT_PATH_PROPERTY = "environment-path"; - public static final String OVERFULL_SIZE_PROPERTY = "overfull-size"; - public static final String UNDERFULL_SIZE_PROPERTY = "underfull-size"; - public static final String OVERFULL_SIZE_ATTRIBUTE = "storeOverfullSize"; - public static final String UNDERFULL_SIZE_ATTRIBUTE = "storeUnderfullSize"; + @Override + public String getType() + { + return QuotaMessageStore.TYPE; + } + + @Override + public MessageStore createMessageStore() + { + return new QuotaMessageStore(); + } + + @Override + public void validateAttributes(Map<String, Object> attributes) + { + } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java index 9407ef2d6c..84d1a9cb1c 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java @@ -21,92 +21,85 @@ package org.apache.qpid.server.store; import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; import java.util.Map; import java.util.UUID; -import org.apache.log4j.Logger; +import java.util.concurrent.ConcurrentHashMap; +import org.apache.log4j.Logger; import org.apache.qpid.server.message.EnqueueableMessage; -import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.util.ServerScopedRuntimeException; - -import java.nio.ByteBuffer; -import java.util.HashMap; +import org.apache.qpid.server.plugin.MessageStoreFactory; public class SlowMessageStore implements MessageStore, DurableConfigurationStore { private static final Logger _logger = Logger.getLogger(SlowMessageStore.class); - private static final String DELAYS = "delays"; + + public static final String TYPE = "SLOW"; + public static final String DELAYS = "delays"; + public static final String REAL_STORE = "realStore"; + + private static final String DEFAULT_DELAY = "default"; + private static final String PRE = "pre"; + private static final String POST = "post"; + private HashMap<String, Long> _preDelays = new HashMap<String, Long>(); private HashMap<String, Long> _postDelays = new HashMap<String, Long>(); private long _defaultDelay = 0L; - private MessageStore _realStore = new MessageStoreCreator().createMessageStore("Memory"); - private DurableConfigurationStore _durableConfigurationStore = (DurableConfigurationStore) _realStore; - private static final String PRE = "pre"; - private static final String POST = "post"; - private String DEFAULT_DELAY = "default"; + private MessageStore _realStore = null; + private DurableConfigurationStore _durableConfigurationStore = null; + + private Map<EventListener, Event[]> _eventListeners = new ConcurrentHashMap<EventListener, Event[]>(); // ***** MessageStore Interface. + @Override public void configureConfigStore(VirtualHost virtualHost, ConfigurationRecoveryHandler recoveryHandler) { _logger.info("Starting SlowMessageStore on Virtualhost:" + virtualHost.getName()); - Object delaysAttr = virtualHost.getAttribute("slowMessageStoreDelays"); + Map<String, Object> messageStoreSettings = virtualHost.getMessageStoreSettings(); + Object delaysAttr = messageStoreSettings.get(DELAYS); - Map delays = (delaysAttr instanceof Map) ? (Map) delaysAttr : Collections.emptyMap(); + @SuppressWarnings({ "unchecked" }) + Map<String,Object> delays = (delaysAttr instanceof Map) ? (Map<String,Object>) delaysAttr : Collections.<String,Object>emptyMap(); configureDelays(delays); - final Object realStoreAttr = virtualHost.getAttribute("realStore"); - String messageStoreClass = realStoreAttr == null ? null : realStoreAttr.toString(); + final Object realStoreAttr = messageStoreSettings.get(REAL_STORE); + String messageStoreType = realStoreAttr == null ? MemoryMessageStore.TYPE : realStoreAttr.toString(); if (delays.containsKey(DEFAULT_DELAY)) { _defaultDelay = Long.parseLong(String.valueOf(delays.get(DEFAULT_DELAY))); } - if (messageStoreClass != null) + _realStore = MessageStoreFactory.FACTORY_LOADER.get(messageStoreType).createMessageStore(); + + if (!_eventListeners.isEmpty()) { - try - { - Class<?> clazz = Class.forName(messageStoreClass); - - Object o = clazz.newInstance(); - - if (!(o instanceof MessageStore)) - { - throw new ClassCastException("Message store class must implement " + MessageStore.class + ". Class " + clazz + - " does not."); - } - _realStore = (MessageStore) o; - if(o instanceof DurableConfigurationStore) - { - _durableConfigurationStore = (DurableConfigurationStore)o; - } - } - catch (ClassNotFoundException e) + for (Iterator<Map.Entry<EventListener, Event[]>> it = _eventListeners.entrySet().iterator(); it.hasNext();) { - throw new ServerScopedRuntimeException("Unable to find message store class", e); - } - catch (InstantiationException e) - { - throw new ServerScopedRuntimeException("Unable to initialise message store class", e); - } - catch (IllegalAccessException e) - { - throw new ServerScopedRuntimeException("Unable to access message store class", e); + Map.Entry<EventListener, Event[]> entry = it.next(); + _realStore.addEventListener(entry.getKey(), entry.getValue()); + it.remove(); } } - _durableConfigurationStore.configureConfigStore(virtualHost, recoveryHandler); + + if (_realStore instanceof DurableConfigurationStore) + { + _durableConfigurationStore = (DurableConfigurationStore)_realStore; + _durableConfigurationStore.configureConfigStore(virtualHost, recoveryHandler); + } } - private void configureDelays(Map<Object, Object> config) + private void configureDelays(Map<String, Object> delays) { - for(Map.Entry<Object, Object> entry : config.entrySet()) + for(Map.Entry<String, Object> entry : delays.entrySet()) { - String key = String.valueOf(entry.getKey()); + String key = entry.getKey(); if (key.startsWith(PRE)) { _preDelays.put(key.substring(PRE.length()), Long.parseLong(String.valueOf(entry.getValue()))); @@ -165,13 +158,14 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore } } - + @Override public void configureMessageStore(VirtualHost virtualHost, MessageStoreRecoveryHandler messageRecoveryHandler, TransactionLogRecoveryHandler tlogRecoveryHandler) { _realStore.configureMessageStore(virtualHost, messageRecoveryHandler, tlogRecoveryHandler); } + @Override public void close() { doPreDelay("close"); @@ -179,12 +173,12 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore doPostDelay("close"); } + @Override public <M extends StorableMessageMetaData> StoredMessage<M> addMessage(M metaData) { return _realStore.addMessage(metaData); } - @Override public void create(UUID id, String type, Map<String, Object> attributes) throws StoreException { @@ -226,6 +220,7 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore doPostDelay("update"); } + @Override public Transaction newTransaction() { doPreDelay("beginTran"); @@ -234,27 +229,12 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore return txn; } - + @Override public boolean isPersistent() { return _realStore.isPersistent(); } - public void storeMessageHeader(Long messageNumber, ServerMessage message) - { - //To change body of implemented methods use File | Settings | File Templates. - } - - public void storeContent(Long messageNumber, long offset, ByteBuffer body) - { - //To change body of implemented methods use File | Settings | File Templates. - } - - public ServerMessage getMessage(Long messageNumber) - { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - private class SlowTransaction implements Transaction { private final Transaction _underlying; @@ -264,6 +244,7 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore _underlying = underlying; } + @Override public void enqueueMessage(TransactionLogResource queue, EnqueueableMessage message) { doPreDelay("enqueueMessage"); @@ -271,6 +252,7 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore doPostDelay("enqueueMessage"); } + @Override public void dequeueMessage(TransactionLogResource queue, EnqueueableMessage message) { doPreDelay("dequeueMessage"); @@ -278,6 +260,7 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore doPostDelay("dequeueMessage"); } + @Override public void commitTran() { doPreDelay("commitTran"); @@ -285,6 +268,7 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore doPostDelay("commitTran"); } + @Override public StoreFuture commitTranAsync() { doPreDelay("commitTran"); @@ -293,6 +277,7 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore return future; } + @Override public void abortTran() { doPreDelay("abortTran"); @@ -300,11 +285,13 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore doPostDelay("abortTran"); } + @Override public void removeXid(long format, byte[] globalId, byte[] branchId) { _underlying.removeXid(format, globalId, branchId); } + @Override public void recordXid(long format, byte[] globalId, byte[] branchId, Record[] enqueues, Record[] dequeues) { _underlying.recordXid(format, globalId, branchId, enqueues, dequeues); @@ -320,7 +307,14 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore @Override public void addEventListener(EventListener eventListener, Event... events) { - _realStore.addEventListener(eventListener, events); + if (_realStore == null) + { + _eventListeners .put(eventListener, events); + } + else + { + _realStore.addEventListener(eventListener, events); + } } @Override @@ -332,7 +326,7 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore @Override public String getStoreType() { - return "SLOW"; + return TYPE; } @Override diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStoreFactory.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStoreFactory.java index 80ef79ae71..62714a75fe 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStoreFactory.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStoreFactory.java @@ -19,10 +19,8 @@ package org.apache.qpid.server.store;/* * */ -import java.util.HashMap; -import java.util.Iterator; import java.util.Map; -import org.apache.commons.configuration.Configuration; + import org.apache.qpid.server.plugin.MessageStoreFactory; public class SlowMessageStoreFactory implements MessageStoreFactory @@ -30,7 +28,7 @@ public class SlowMessageStoreFactory implements MessageStoreFactory @Override public String getType() { - return "SLOW"; + return SlowMessageStore.TYPE; } @Override @@ -40,43 +38,6 @@ public class SlowMessageStoreFactory implements MessageStoreFactory } @Override - public Map<String, Object> convertStoreConfiguration(Configuration storeConfiguration) - { - Map<String, Object> convertedMap = new HashMap<String, Object>(); - Configuration delaysConfig = storeConfiguration.subset("delays"); - - @SuppressWarnings("unchecked") - Iterator<String> delays = delaysConfig.getKeys(); - - Map<String,Long> delaysMap = new HashMap<String, Long>(); - - while (delays.hasNext()) - { - String key = delays.next(); - - if (key.endsWith("pre")) - { - delaysMap.put("pre"+key.substring(0, key.length() - 4), delaysConfig.getLong(key)); - } - else if (key.endsWith("post")) - { - delaysMap.put("post"+key.substring(0, key.length() - 5), delaysConfig.getLong(key)); - } - } - - if(!delaysMap.isEmpty()) - { - convertedMap.put("slowMessageStoreDelays",delaysMap); - } - - - convertedMap.put("realStore", storeConfiguration.getString("realStore", null)); - - - return convertedMap; - } - - @Override public void validateAttributes(Map<String, Object> attributes) { } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/StoreOverfullTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/StoreOverfullTest.java index 31e6a5613f..3dea6fd5bb 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/StoreOverfullTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/StoreOverfullTest.java @@ -20,6 +20,8 @@ */ package org.apache.qpid.server.store; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; @@ -37,7 +39,9 @@ import org.apache.qpid.client.AMQDestination; import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.AMQSession; import org.apache.qpid.exchange.ExchangeDefaults; +import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.test.utils.TestBrokerConfiguration; public class StoreOverfullTest extends QpidBrokerTestCase { @@ -60,9 +64,13 @@ public class StoreOverfullTest extends QpidBrokerTestCase public void setUp() throws Exception { - setVirtualHostConfigurationProperty("virtualhosts.virtualhost.test.store.class", QuotaMessageStore.class.getName()); - setVirtualHostConfigurationProperty("virtualhosts.virtualhost.test.store.overfull-size", String.valueOf(OVERFULL_SIZE)); - setVirtualHostConfigurationProperty("virtualhosts.virtualhost.test.store.underfull-size", String.valueOf(UNDERFULL_SIZE)); + Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); + messageStoreSettings.put(MessageStore.STORE_TYPE, QuotaMessageStore.TYPE); + messageStoreSettings.put(MessageStore.OVERFULL_SIZE, OVERFULL_SIZE); + messageStoreSettings.put(MessageStore.UNDERFULL_SIZE, UNDERFULL_SIZE); + + TestBrokerConfiguration config = getBrokerConfiguration(); + config.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST, VirtualHost.MESSAGE_STORE_SETTINGS, messageStoreSettings); super.setUp(); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/AccessControlProviderRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/AccessControlProviderRestTest.java index 312443cfa7..f87113465c 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/AccessControlProviderRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/AccessControlProviderRestTest.java @@ -27,7 +27,6 @@ import java.util.List; import java.util.Map; import java.util.UUID; -import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.management.plugin.HttpManagement; import org.apache.qpid.server.model.AccessControlProvider; @@ -54,7 +53,7 @@ public class AccessControlProviderRestTest extends QpidRestTestCase "ACL DENY-LOG ALL ALL"; @Override - protected void customizeConfiguration() throws ConfigurationException, IOException + protected void customizeConfiguration() throws IOException { super.customizeConfiguration(); getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER, OTHER_USER); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/AnonymousAccessRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/AnonymousAccessRestTest.java index d227460e6a..9bf815adf7 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/AnonymousAccessRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/AnonymousAccessRestTest.java @@ -24,7 +24,6 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.management.plugin.HttpManagement; import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.Broker; @@ -46,7 +45,7 @@ public class AnonymousAccessRestTest extends QpidRestTestCase } @Override - protected void customizeConfiguration() throws ConfigurationException, IOException + protected void customizeConfiguration() throws IOException { super.customizeConfiguration(); TestBrokerConfiguration config = getBrokerConfiguration(); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java index c749318595..9ad08ef331 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java @@ -31,7 +31,18 @@ import java.util.Map; import javax.jms.JMSException; import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.server.model.*; +import org.apache.qpid.server.model.Binding; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Connection; +import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.ExclusivityPolicy; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Protocol; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.model.adapter.AbstractConfiguredObject; import org.apache.qpid.test.utils.TestBrokerConfiguration; @@ -50,11 +61,9 @@ public class Asserts ConfiguredObject.LAST_UPDATED_TIME, ConfiguredObject.DESCRIPTION, VirtualHost.SUPPORTED_QUEUE_TYPES, - VirtualHost.STORE_PATH, - VirtualHost.CONFIG_PATH, VirtualHost.TYPE, - VirtualHost.CONFIG_STORE_PATH, - VirtualHost.CONFIG_STORE_TYPE); + VirtualHost.CONFIGURATION_STORE_SETTINGS, + VirtualHost.SECURITY_ACL); assertEquals("Unexpected value of attribute " + VirtualHost.NAME, virtualHostName, @@ -146,7 +155,7 @@ public class Asserts @SuppressWarnings("unchecked") Map<String, Object> statistics = (Map<String, Object>) queueData.get(Asserts.STATISTICS_ATTRIBUTE); - Asserts.assertAttributesPresent(statistics, + Asserts.assertAttributesPresent(statistics, "bindingCount", "consumerCount", "consumerCountWithCredit", @@ -226,7 +235,7 @@ public class Asserts @SuppressWarnings("unchecked") Map<String, Object> statistics = (Map<String, Object>) connectionData.get(STATISTICS_ATTRIBUTE); - + assertAttributesPresent(statistics, "bytesIn", diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BasicAuthRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BasicAuthRestTest.java index c8320a6d82..81177b8c08 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BasicAuthRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BasicAuthRestTest.java @@ -29,10 +29,8 @@ import java.util.Collections; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.management.plugin.HttpManagement; import org.apache.qpid.server.model.Port; -import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.Transport; import org.apache.qpid.test.utils.TestBrokerConfiguration; @@ -49,12 +47,12 @@ public class BasicAuthRestTest extends QpidRestTestCase } @Override - protected void customizeConfiguration() throws ConfigurationException, IOException + protected void customizeConfiguration() throws IOException { //do nothing, we will configure this locally } - private void configure(boolean useSsl) throws ConfigurationException, IOException + private void configure(boolean useSsl) throws IOException { getRestTestHelper().setUseSsl(useSsl); if (useSsl) diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BindingRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BindingRestTest.java index 666c78f070..6ba8df075b 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BindingRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BindingRestTest.java @@ -30,12 +30,18 @@ import org.apache.qpid.server.model.Binding; public class BindingRestTest extends QpidRestTestCase { + @Override + public void setUp() throws Exception + { + super.setUp(); + getRestTestHelper().createTestQueues(); + } + public void testGetAllBindings() throws Exception { - List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding"); + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test"); assertNotNull("Bindings cannot be null", bindings); - assertTrue("Unexpected number of bindings: " + bindings.size(), - bindings.size() >= EXPECTED_VIRTUALHOSTS.length * EXPECTED_QUEUES.length); + assertEquals("Unexpected number of bindings", RestTestHelper.EXPECTED_QUEUES.length, bindings.size()); for (Map<String, Object> binding : bindings) { Asserts.assertBinding((String) binding.get(Binding.NAME), (String) binding.get(Binding.EXCHANGE), binding); @@ -46,8 +52,8 @@ public class BindingRestTest extends QpidRestTestCase { List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test"); assertNotNull("Bindings cannot be null", bindings); - assertEquals("Unexpected number of bindings", EXPECTED_QUEUES.length, bindings.size()); - for (String queueName : EXPECTED_QUEUES) + assertEquals("Unexpected number of bindings", RestTestHelper.EXPECTED_QUEUES.length, bindings.size()); + for (String queueName : RestTestHelper.EXPECTED_QUEUES) { Map<String, Object> searchAttributes = new HashMap<String, Object>(); searchAttributes.put(Binding.NAME, queueName); @@ -62,8 +68,8 @@ public class BindingRestTest extends QpidRestTestCase { List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct"); assertNotNull("Bindings cannot be null", bindings); - assertEquals("Unexpected number of bindings", EXPECTED_QUEUES.length, bindings.size()); - for (String queueName : EXPECTED_QUEUES) + assertEquals("Unexpected number of bindings", RestTestHelper.EXPECTED_QUEUES.length, bindings.size()); + for (String queueName : RestTestHelper.EXPECTED_QUEUES) { Map<String, Object> binding = getRestTestHelper().find(Binding.NAME, queueName, bindings); Asserts.assertBinding(queueName, "amq.direct", binding); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsClientCertAuthTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsClientCertAuthTest.java index e92b38b4e0..3a85ad5431 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsClientCertAuthTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsClientCertAuthTest.java @@ -20,25 +20,22 @@ */ package org.apache.qpid.systest.rest; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.qpid.server.model.AuthenticationProvider; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.Port; -import org.apache.qpid.server.model.Protocol; -import org.apache.qpid.server.model.Transport; -import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManagerFactory; -import org.apache.qpid.server.security.auth.manager.ExternalAuthenticationManagerFactory; -import org.apache.qpid.test.utils.TestBrokerConfiguration; +import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE; +import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE_PASSWORD; +import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE; +import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE_PASSWORD; import java.io.IOException; import java.util.Collections; import java.util.HashMap; import java.util.Map; -import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE; -import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE_PASSWORD; -import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE; -import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE_PASSWORD; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Protocol; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.security.auth.manager.ExternalAuthenticationManagerFactory; +import org.apache.qpid.test.utils.TestBrokerConfiguration; public class BrokerRestHttpsClientCertAuthTest extends QpidRestTestCase { @@ -56,7 +53,7 @@ public class BrokerRestHttpsClientCertAuthTest extends QpidRestTestCase } @Override - protected void customizeConfiguration() throws ConfigurationException, IOException + protected void customizeConfiguration() throws IOException { super.customizeConfiguration(); getRestTestHelper().setUseSslAuth(true); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java index ad789e6fa1..b7846bb09c 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java @@ -28,7 +28,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; -import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.Port; @@ -49,7 +48,7 @@ public class BrokerRestHttpsTest extends QpidRestTestCase } @Override - protected void customizeConfiguration() throws ConfigurationException, IOException + protected void customizeConfiguration() throws IOException { super.customizeConfiguration(); getRestTestHelper().setUseSsl(true); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java index 1ccd31a83a..473cf2beca 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java @@ -41,7 +41,7 @@ import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.model.adapter.AbstractConfiguredObject; -import org.apache.qpid.server.store.MessageStoreCreator; +import org.apache.qpid.server.plugin.MessageStoreFactory; import org.apache.qpid.test.client.UnroutableMessageTestExceptionListener; import org.apache.qpid.test.utils.TestBrokerConfiguration; import org.apache.qpid.util.SystemUtils; @@ -271,7 +271,7 @@ public class BrokerRestTest extends QpidRestTestCase @SuppressWarnings("unchecked") Collection<String> supportedVirtualHostStoreTypes = (Collection<String>)brokerDetails.get(Broker.SUPPORTED_VIRTUALHOST_STORE_TYPES); - Collection<String> expectedSupportedVirtualHostStoreTypes = new MessageStoreCreator().getStoreTypes(); + Collection<String> expectedSupportedVirtualHostStoreTypes = MessageStoreFactory.FACTORY_LOADER.getSupportedTypes(); assertEquals("Unexpected supported virtual host store types", new HashSet<String>(expectedSupportedVirtualHostStoreTypes), new HashSet<String>(supportedVirtualHostStoreTypes)); } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/ExchangeRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/ExchangeRestTest.java index 1da1c6394e..962c71583c 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/ExchangeRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/ExchangeRestTest.java @@ -30,6 +30,13 @@ import org.apache.qpid.server.model.Exchange; public class ExchangeRestTest extends QpidRestTestCase { + @Override + public void setUp() throws Exception + { + super.setUp(); + getRestTestHelper().createTestQueues(); + } + public void testGet() throws Exception { List<Map<String, Object>> exchanges = getRestTestHelper().getJsonAsList("/rest/exchange"); @@ -98,7 +105,7 @@ public class ExchangeRestTest extends QpidRestTestCase { @SuppressWarnings("unchecked") List<Map<String, Object>> bindings = (List<Map<String, Object>>) exchange.get("bindings"); - for (String queueName : EXPECTED_QUEUES) + for (String queueName : RestTestHelper.EXPECTED_QUEUES) { Map<String, Object> binding = getRestTestHelper().find(Binding.NAME, queueName, bindings); Asserts.assertBinding(queueName, (String) exchange.get(Exchange.NAME), binding); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesProviderRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesProviderRestTest.java index 85a50c4ce8..80dd7e11a4 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesProviderRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesProviderRestTest.java @@ -27,7 +27,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.LifetimePolicy; @@ -71,7 +70,7 @@ public class PreferencesProviderRestTest extends QpidRestTestCase } @Override - protected void customizeConfiguration() throws ConfigurationException, IOException + protected void customizeConfiguration() throws IOException { super.customizeConfiguration(); Map<String, Object> anonymousAuthProviderAttributes = new HashMap<String, Object>(); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesRestTest.java index 46acd9e77b..c4b182da1a 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesRestTest.java @@ -25,7 +25,6 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.model.PreferencesProvider; import org.apache.qpid.server.model.adapter.FileSystemPreferencesProvider; import org.apache.qpid.test.utils.TestBrokerConfiguration; @@ -58,7 +57,7 @@ public class PreferencesRestTest extends QpidRestTestCase } @Override - protected void customizeConfiguration() throws ConfigurationException, IOException + protected void customizeConfiguration() throws IOException { super.customizeConfiguration(); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java index ce501adeb6..de5c2f561f 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java @@ -24,7 +24,6 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.management.plugin.HttpManagement; import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.Port; @@ -42,7 +41,6 @@ public class QpidRestTestCase extends QpidBrokerTestCase public static final String TEST3_VIRTUALHOST = "test3"; public static final String[] EXPECTED_VIRTUALHOSTS = { TEST1_VIRTUALHOST, TEST2_VIRTUALHOST, TEST3_VIRTUALHOST}; - public static final String[] EXPECTED_QUEUES = { "queue", "ping" }; public static final String[] EXPECTED_EXCHANGES = { "amq.fanout", "amq.match", "amq.direct","amq.topic" }; private RestTestHelper _restTestHelper = new RestTestHelper(findFreePort()); @@ -60,12 +58,6 @@ public class QpidRestTestCase extends QpidBrokerTestCase for (String virtualhost : EXPECTED_VIRTUALHOSTS) { createTestVirtualHost(0, virtualhost); - - for (String queue : EXPECTED_QUEUES) - { - setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + virtualhost + ".queues.exchange", "amq.direct"); - setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + virtualhost + ".queues.queue(-1).name", queue); - } } customizeConfiguration(); @@ -85,7 +77,7 @@ public class QpidRestTestCase extends QpidBrokerTestCase } } - protected void customizeConfiguration() throws ConfigurationException, IOException + protected void customizeConfiguration() throws IOException { TestBrokerConfiguration config = getBrokerConfiguration(); config.addHttpManagementConfiguration(); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QueueRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QueueRestTest.java index faccca9e9d..297d15db13 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QueueRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QueueRestTest.java @@ -83,10 +83,8 @@ public class QueueRestTest extends QpidRestTestCase { String queueName = getTestQueueName(); List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/queue/test"); - assertEquals("Unexpected number of queues", EXPECTED_QUEUES.length + 1, queues.size()); - String[] expectedQueues = new String[EXPECTED_QUEUES.length + 1]; - System.arraycopy(EXPECTED_QUEUES, 0, expectedQueues, 0, EXPECTED_QUEUES.length); - expectedQueues[EXPECTED_QUEUES.length] = queueName; + assertEquals("Unexpected number of queues", 1, queues.size()); + String[] expectedQueues = new String[]{queueName}; for (String name : expectedQueues) { diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java index ef87457925..7050dcfc33 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java @@ -52,9 +52,10 @@ import javax.servlet.http.HttpServletResponse; import junit.framework.Assert; import org.apache.commons.codec.binary.Base64; -import org.apache.commons.configuration.ConfigurationException; import org.apache.log4j.Logger; import org.apache.qpid.server.BrokerOptions; +import org.apache.qpid.server.model.Binding; +import org.apache.qpid.server.model.Queue; import org.apache.qpid.ssl.SSLContextFactory; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.test.utils.TestBrokerConfiguration; @@ -80,6 +81,7 @@ public class RestTestHelper private File _passwdFile; private boolean _useSslAuth; + static final String[] EXPECTED_QUEUES = { "queue", "ping" }; public RestTestHelper(int httpPort) { @@ -226,6 +228,11 @@ public class RestTestHelper public Map<String, Object> find(String name, Object value, List<Map<String, Object>> data) { + if (data == null) + { + return null; + } + for (Map<String, Object> map : data) { Object mapValue = map.get(name); @@ -437,7 +444,7 @@ public class RestTestHelper /** * Create password file that follows the convention username=password, which is deleted by {@link #tearDown()} */ - public void configureTemporaryPasswordFile(QpidBrokerTestCase testCase, String... users) throws ConfigurationException, IOException + public void configureTemporaryPasswordFile(QpidBrokerTestCase testCase, String... users) throws IOException { _passwdFile = createTemporaryPasswdFile(users); @@ -509,4 +516,22 @@ public class RestTestHelper _useSslAuth = useSslAuth; _useSsl = true; } + + public void createTestQueues() throws IOException, JsonGenerationException, JsonMappingException + { + for (int i = 0; i < EXPECTED_QUEUES.length; i++) + { + String queueName = EXPECTED_QUEUES[i]; + Map<String, Object> queueData = new HashMap<String, Object>(); + queueData.put(Queue.NAME, queueName); + queueData.put(Queue.DURABLE, Boolean.FALSE); + submitRequest("/rest/queue/test/" + queueName, "PUT", queueData); + + Map<String, Object> bindingData = new HashMap<String, Object>(); + bindingData.put(Binding.NAME, queueName); + bindingData.put(Binding.QUEUE, queueName); + bindingData.put(Binding.EXCHANGE, "amq.direct"); + submitRequest("/rest/binding/test/amq.direct/" + queueName + "/" + queueName, "PUT", queueData); + } + } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java index 590858fbf5..6ec2a02ba1 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java @@ -35,7 +35,6 @@ import java.util.List; import java.util.Map; import org.apache.commons.codec.binary.Base64; -import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.security.auth.manager.Base64MD5PasswordFileAuthenticationManagerFactory; import org.apache.qpid.test.utils.TestBrokerConfiguration; @@ -347,7 +346,7 @@ public class SaslRestTest extends QpidRestTestCase } } - private void configureBase64MD5FilePrincipalDatabase() throws IOException, ConfigurationException + private void configureBase64MD5FilePrincipalDatabase() throws IOException { // generate user password entry String passwordFileEntry; @@ -357,7 +356,7 @@ public class SaslRestTest extends QpidRestTestCase } catch (NoSuchAlgorithmException e) { - throw new ConfigurationException(e); + throw new RuntimeException(e); } // store the entry in the file diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java index da72dd6f05..cf551ae315 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java @@ -30,6 +30,13 @@ import org.apache.qpid.test.utils.TestBrokerConfiguration; public class StructureRestTest extends QpidRestTestCase { + @Override + public void setUp() throws Exception + { + super.setUp(); + getRestTestHelper().createTestQueues(); + } + public void testGet() throws Exception { Map<String, Object> structure = getRestTestHelper().getJsonAsMap("/rest/structure"); @@ -53,50 +60,52 @@ public class StructureRestTest extends QpidRestTestCase Map<String, Object> host = getRestTestHelper().find("name", hostName, virtualhosts); assertNotNull("Host " + hostName + " is not found ", host); assertNode(host, hostName); + } + + String hostName = "test"; + Map<String, Object> host = getRestTestHelper().find("name", hostName, virtualhosts); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> queues = (List<Map<String, Object>>) host.get("queues"); + assertNotNull("Host " + hostName + " queues are not found ", queues); + for (String queueName : RestTestHelper.EXPECTED_QUEUES) + { + Map<String, Object> queue = getRestTestHelper().find("name", queueName, queues); + assertNotNull(hostName + " queue " + queueName + " is not found ", queue); + assertNode(queue, queueName); @SuppressWarnings("unchecked") - List<Map<String, Object>> queues = (List<Map<String, Object>>) host.get("queues"); - assertNotNull("Host " + hostName + " queues are not found ", queues); - for (String queueName : EXPECTED_QUEUES) + List<Map<String, Object>> bindings = (List<Map<String, Object>>) queue.get("bindings"); + assertNotNull(hostName + " queue " + queueName + " bindings are not found ", queues); + for (Map<String, Object> binding : bindings) { - Map<String, Object> queue = getRestTestHelper().find("name", queueName, queues); - assertNotNull(hostName + " queue " + queueName + " is not found ", queue); - assertNode(queue, queueName); - - @SuppressWarnings("unchecked") - List<Map<String, Object>> bindings = (List<Map<String, Object>>) queue.get("bindings"); - assertNotNull(hostName + " queue " + queueName + " bindings are not found ", queues); - for (Map<String, Object> binding : bindings) - { - assertNode(binding, queueName); - } + assertNode(binding, queueName); } + } - @SuppressWarnings("unchecked") - List<Map<String, Object>> exchanges = (List<Map<String, Object>>) host.get("exchanges"); - assertNotNull("Host " + hostName + " exchanges are not found ", exchanges); - for (String exchangeName : EXPECTED_EXCHANGES) + @SuppressWarnings("unchecked") + List<Map<String, Object>> exchanges = (List<Map<String, Object>>) host.get("exchanges"); + assertNotNull("Host " + hostName + " exchanges are not found ", exchanges); + for (String exchangeName : EXPECTED_EXCHANGES) + { + Map<String, Object> exchange = getRestTestHelper().find("name", exchangeName, exchanges); + assertNotNull("Exchange " + exchangeName + " is not found ", exchange); + assertNode(exchange, exchangeName); + if (ExchangeDefaults.DIRECT_EXCHANGE_NAME.equalsIgnoreCase(exchangeName) || + ExchangeDefaults.DEFAULT_EXCHANGE_NAME.equalsIgnoreCase(exchangeName)) { - Map<String, Object> exchange = getRestTestHelper().find("name", exchangeName, exchanges); - assertNotNull("Exchange " + exchangeName + " is not found ", exchange); - assertNode(exchange, exchangeName); - if (ExchangeDefaults.DIRECT_EXCHANGE_NAME.equalsIgnoreCase(exchangeName) || - ExchangeDefaults.DEFAULT_EXCHANGE_NAME.equalsIgnoreCase(exchangeName)) + @SuppressWarnings("unchecked") + List<Map<String, Object>> bindings = (List<Map<String, Object>>) exchange.get("bindings"); + assertNotNull(hostName + " exchange " + exchangeName + " bindings are not found ", bindings); + for (String queueName : RestTestHelper.EXPECTED_QUEUES) { - @SuppressWarnings("unchecked") - List<Map<String, Object>> bindings = (List<Map<String, Object>>) exchange.get("bindings"); - assertNotNull(hostName + " exchange " + exchangeName + " bindings are not found ", bindings); - for (String queueName : EXPECTED_QUEUES) - { - Map<String, Object> binding = getRestTestHelper().find("name", queueName, bindings); - assertNotNull(hostName + " exchange " + exchangeName + " binding " + queueName + " is not found", binding); - assertNode(binding, queueName); - } + Map<String, Object> binding = getRestTestHelper().find("name", queueName, bindings); + assertNotNull(hostName + " exchange " + exchangeName + " binding " + queueName + " is not found", binding); + assertNode(binding, queueName); } } } - String httpPortName = TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT; Map<String, Object> portData = getRestTestHelper().find(Port.NAME, httpPortName, ports); assertNotNull("Http Port " + httpPortName + " is not found", portData); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/UserPreferencesRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/UserPreferencesRestTest.java index 9965587343..296ccf9221 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/UserPreferencesRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/UserPreferencesRestTest.java @@ -28,7 +28,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.model.PreferencesProvider; import org.apache.qpid.server.model.User; import org.apache.qpid.server.model.adapter.FileSystemPreferencesProvider; @@ -63,7 +62,7 @@ public class UserPreferencesRestTest extends QpidRestTestCase } @Override - protected void customizeConfiguration() throws ConfigurationException, IOException + protected void customizeConfiguration() throws IOException { super.customizeConfiguration(); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java index eac43e70a4..1ae1be3101 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java @@ -30,15 +30,13 @@ import java.util.Map; import javax.jms.Session; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.server.model.Exchange; import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.queue.ConflationQueue; +import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.virtualhost.StandardVirtualHostFactory; -import org.apache.qpid.test.utils.TestFileUtils; import org.apache.qpid.util.FileUtils; import org.codehaus.jackson.JsonGenerationException; import org.codehaus.jackson.map.JsonMappingException; @@ -67,16 +65,18 @@ public class VirtualHostRestTest extends QpidRestTestCase { // create AMQP connection to get connection JSON details _connection = (AMQConnection) getConnection(); - _connection.createSession(true, Session.SESSION_TRANSACTED); + Session session = _connection.createSession(true, Session.SESSION_TRANSACTED); + session.createConsumer(getTestQueue()); Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); Asserts.assertVirtualHost("test", hostDetails); @SuppressWarnings("unchecked") Map<String, Object> statistics = (Map<String, Object>) hostDetails.get(Asserts.STATISTICS_ATTRIBUTE); + assertEquals("Unexpected number of exchanges in statistics", EXPECTED_EXCHANGES.length, statistics.get( "exchangeCount")); - assertEquals("Unexpected number of queues in statistics", EXPECTED_QUEUES.length, statistics.get("queueCount")); + assertEquals("Unexpected number of queues in statistics", 1, statistics.get("queueCount")); assertEquals("Unexpected number of connections in statistics", 1, statistics.get("connectionCount")); @SuppressWarnings("unchecked") @@ -89,13 +89,10 @@ public class VirtualHostRestTest extends QpidRestTestCase @SuppressWarnings("unchecked") List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VIRTUALHOST_QUEUES_ATTRIBUTE); - assertEquals("Unexpected number of queues", EXPECTED_QUEUES.length, queues.size()); - Map<String, Object> queue = getRestTestHelper().find(Queue.NAME, "queue", queues); - Map<String, Object> ping = getRestTestHelper().find(Queue.NAME, "ping", queues); - Asserts.assertQueue("queue", "standard", queue); - Asserts.assertQueue("ping", "standard", ping); - assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.FALSE, queue.get(Queue.DURABLE)); - assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.FALSE, ping.get(Queue.DURABLE)); + assertEquals("Unexpected number of queues", 1, queues.size()); + Map<String, Object> queue = getRestTestHelper().find(Queue.NAME, getTestQueueName(), queues); + Asserts.assertQueue(getTestQueueName(), "standard", queue); + assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, queue.get(Queue.DURABLE)); @SuppressWarnings("unchecked") List<Map<String, Object>> connections = (List<Map<String, Object>>) hostDetails @@ -115,34 +112,10 @@ public class VirtualHostRestTest extends QpidRestTestCase restartBroker(); Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/" + hostName); Asserts.assertVirtualHost(hostName, hostDetails); - assertEquals("Unexpected store type", storeType, hostDetails.get(VirtualHost.STORE_TYPE)); - assertNewVirtualHost(hostDetails); - } - finally - { - if (storeLocation != null) - { - FileUtils.delete(new File(storeLocation), true); - } - } - } - - public void testPutCreateVirtualHostUsingConfigPath() throws Exception - { - String hostName = getName(); - File configFile = TestFileUtils.createTempFile(this, hostName + "-config.xml"); - String configPath = configFile.getAbsolutePath(); - String storeLocation = getStoreLocation(hostName); - createAndSaveVirtualHostConfiguration(hostName, configFile, storeLocation); - createHost(hostName, null, configPath); - try - { - // make sure that the host is saved in the broker store - restartBroker(); - Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/" + hostName); - Asserts.assertVirtualHost(hostName, hostDetails); - assertEquals("Unexpected config path", configPath, hostDetails.get(VirtualHost.CONFIG_PATH)); + @SuppressWarnings("unchecked") + Map<String, Object> messageStoreSettings = (Map<String, Object>) hostDetails.get(VirtualHost.MESSAGE_STORE_SETTINGS); + assertEquals("Unexpected store type", storeType, messageStoreSettings.get(MessageStore.STORE_TYPE)); assertNewVirtualHost(hostDetails); } @@ -152,7 +125,6 @@ public class VirtualHostRestTest extends QpidRestTestCase { FileUtils.delete(new File(storeLocation), true); } - configFile.delete(); } } @@ -187,24 +159,30 @@ public class VirtualHostRestTest extends QpidRestTestCase String hostToUpdate = TEST3_VIRTUALHOST; Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/" + hostToUpdate); Asserts.assertVirtualHost(hostToUpdate, hostDetails); - String configPath = (String)hostDetails.get(VirtualHost.CONFIG_PATH); - assertNotNull("Unexpected host configuration", configPath); + @SuppressWarnings("unchecked") + Map<String, Object> attributes = (Map<String, Object>)hostDetails.get(VirtualHost.MESSAGE_STORE_SETTINGS); + String configPath = (String) attributes.get(MessageStore.STORE_PATH); String storeType = getTestProfileMessageStoreType(); String storeLocation = getStoreLocation(hostToUpdate); + Map<String, Object> newMessageStoreSettings = new HashMap<String, Object>(); + newMessageStoreSettings.put(MessageStore.STORE_TYPE, storeType); + newMessageStoreSettings.put(MessageStore.STORE_PATH, storeLocation); + Map<String, Object> newAttributes = new HashMap<String, Object>(); newAttributes.put(VirtualHost.NAME, hostToUpdate); - newAttributes.put(VirtualHost.STORE_TYPE, storeType); - newAttributes.put(VirtualHost.STORE_PATH, storeLocation); + newAttributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, newMessageStoreSettings); int response = getRestTestHelper().submitRequest("/rest/virtualhost/" + hostToUpdate, "PUT", newAttributes); assertEquals("Unexpected response code", 409, response); restartBroker(); - hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/" + hostToUpdate); - Asserts.assertVirtualHost(hostToUpdate, hostDetails); - assertEquals("Unexpected config path", configPath, hostDetails.get(VirtualHost.CONFIG_PATH)); + Map<String, Object> rereadHostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/" + hostToUpdate); + Asserts.assertVirtualHost(hostToUpdate, rereadHostDetails); + @SuppressWarnings("unchecked") + Map<String, Object> rereadMessageStoreSettings = (Map<String,Object>)rereadHostDetails.get(VirtualHost.MESSAGE_STORE_SETTINGS); + assertEquals("Unexpected config path", configPath, rereadMessageStoreSettings.get(MessageStore.STORE_PATH)); } public void testPutCreateQueue() throws Exception @@ -557,34 +535,19 @@ public class VirtualHostRestTest extends QpidRestTestCase private int tryCreateVirtualHost(String hostName, String storeType, String storePath, String configPath) throws IOException, JsonGenerationException, JsonMappingException { + Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); + messageStoreSettings.put(MessageStore.STORE_PATH, storePath); + messageStoreSettings.put(MessageStore.STORE_TYPE, storeType); + Map<String, Object> hostData = new HashMap<String, Object>(); hostData.put(VirtualHost.NAME, hostName); - if (storeType == null) - { - hostData.put(VirtualHost.CONFIG_PATH, configPath); - } - else - { - hostData.put(VirtualHost.TYPE, StandardVirtualHostFactory.TYPE); - hostData.put(VirtualHost.STORE_PATH, storePath); - hostData.put(VirtualHost.STORE_TYPE, storeType); - } + hostData.put(VirtualHost.TYPE, StandardVirtualHostFactory.TYPE); + hostData.put(VirtualHost.MESSAGE_STORE_SETTINGS, messageStoreSettings); return getRestTestHelper().submitRequest("/rest/virtualhost/" + hostName, "PUT", hostData); } - private XMLConfiguration createAndSaveVirtualHostConfiguration(String hostName, File configFile, String storeLocation) - throws ConfigurationException - { - XMLConfiguration testConfiguration = new XMLConfiguration(); - testConfiguration.setProperty("virtualhost." + hostName + ".store.class", - getTestProfileMessageStoreClassName()); - testConfiguration.setProperty("virtualhost." + hostName + ".store.environment-path", storeLocation); - testConfiguration.save(configFile); - return testConfiguration; - } - private void assertNewVirtualHost(Map<String, Object> hostDetails) { @SuppressWarnings("unchecked") diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java index 7f41a8eb2e..ec389e55f1 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java @@ -27,7 +27,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.management.plugin.HttpManagement; import org.apache.qpid.server.model.AccessControlProvider; import org.apache.qpid.server.model.AuthenticationProvider; @@ -43,6 +42,7 @@ import org.apache.qpid.server.security.acl.AbstractACLTestCase; import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManagerFactory; import org.apache.qpid.server.security.auth.manager.PlainPasswordFileAuthenticationManagerFactory; import org.apache.qpid.server.security.group.FileGroupManagerFactory; +import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.virtualhost.StandardVirtualHostFactory; import org.apache.qpid.systest.rest.QpidRestTestCase; import org.apache.qpid.test.utils.TestBrokerConfiguration; @@ -58,7 +58,7 @@ public class BrokerACLTest extends QpidRestTestCase private String _secondaryAclFileContent = ""; @Override - protected void customizeConfiguration() throws ConfigurationException, IOException + protected void customizeConfiguration() throws IOException { super.customizeConfiguration(); getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER); @@ -977,10 +977,13 @@ public class BrokerACLTest extends QpidRestTestCase private int createHost(String hostName) throws Exception { + Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); + messageStoreSettings.put(MessageStore.STORE_PATH, getStoreLocation(hostName)); + messageStoreSettings.put(MessageStore.STORE_TYPE, getTestProfileMessageStoreType()); + Map<String, Object> hostData = new HashMap<String, Object>(); hostData.put(VirtualHost.NAME, hostName); - hostData.put(VirtualHost.STORE_PATH, getStoreLocation(hostName)); - hostData.put(VirtualHost.STORE_TYPE, getTestProfileMessageStoreType()); + hostData.put(VirtualHost.MESSAGE_STORE_SETTINGS, messageStoreSettings); hostData.put(VirtualHost.TYPE, StandardVirtualHostFactory.TYPE); return getRestTestHelper().submitRequest("/rest/virtualhost/" + hostName, "PUT", hostData); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/ExchangeRestACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/ExchangeRestACLTest.java index b39d994198..b63df34b98 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/ExchangeRestACLTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/ExchangeRestACLTest.java @@ -25,10 +25,10 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.management.plugin.HttpManagement; import org.apache.qpid.server.model.Binding; import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.security.acl.AbstractACLTestCase; import org.apache.qpid.systest.rest.QpidRestTestCase; import org.apache.qpid.test.utils.TestBrokerConfiguration; @@ -39,15 +39,17 @@ public class ExchangeRestACLTest extends QpidRestTestCase { private static final String ALLOWED_USER = "user1"; private static final String DENIED_USER = "user2"; + private String _queueName; @Override - protected void customizeConfiguration() throws ConfigurationException, IOException + protected void customizeConfiguration() throws IOException { super.customizeConfiguration(); getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER); AbstractACLTestCase.writeACLFileUtil(this, null, "ACL ALLOW-LOG ALL ACCESS MANAGEMENT", + "ACL ALLOW-LOG " + ALLOWED_USER + " CREATE QUEUE", "ACL ALLOW-LOG " + ALLOWED_USER + " CREATE EXCHANGE", "ACL DENY-LOG " + DENIED_USER + " CREATE EXCHANGE", "ACL ALLOW-LOG " + ALLOWED_USER + " UPDATE EXCHANGE", @@ -64,6 +66,20 @@ public class ExchangeRestACLTest extends QpidRestTestCase HttpManagement.HTTP_BASIC_AUTHENTICATION_ENABLED, true); } + @Override + public void setUp() throws Exception + { + super.setUp(); + _queueName = getTestQueueName(); + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + Map<String, Object> queueData = new HashMap<String, Object>(); + queueData.put(Queue.NAME, _queueName); + queueData.put(Queue.DURABLE, Boolean.TRUE); + int status = getRestTestHelper().submitRequest("/rest/queue/test/" + _queueName, "PUT", queueData); + assertEquals("Unexpected status", 201, status); + + } + public void testCreateExchangeAllowed() throws Exception { getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); @@ -210,10 +226,10 @@ public class ExchangeRestACLTest extends QpidRestTestCase { Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(Binding.NAME, bindingName); - attributes.put(Binding.QUEUE, "queue"); + attributes.put(Binding.QUEUE, _queueName); attributes.put(Binding.EXCHANGE, "amq.direct"); - int responseCode = getRestTestHelper().submitRequest("/rest/binding/test/amq.direct/queue/" + bindingName, "PUT", attributes); + int responseCode = getRestTestHelper().submitRequest("/rest/binding/test/amq.direct/" + _queueName + "/" + bindingName, "PUT", attributes); return responseCode; } @@ -229,7 +245,7 @@ public class ExchangeRestACLTest extends QpidRestTestCase private void assertBindingExistence(String bindingName, boolean exists) throws Exception { - List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/queue/" + bindingName); + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/" + _queueName + "/" + bindingName); assertEquals("Unexpected result", exists, !bindings.isEmpty()); } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java index 9a578d01fb..aff1eac9cf 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java @@ -28,7 +28,6 @@ import java.util.Properties; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.management.plugin.HttpManagement; import org.apache.qpid.server.security.acl.AbstractACLTestCase; import org.apache.qpid.systest.rest.QpidRestTestCase; @@ -58,7 +57,7 @@ public class GroupRestACLTest extends QpidRestTestCase } @Override - protected void customizeConfiguration() throws ConfigurationException, IOException + protected void customizeConfiguration() throws IOException { super.customizeConfiguration(); getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_MANAGEMENT, HttpManagement.HTTP_BASIC_AUTHENTICATION_ENABLED, true); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/LogViewerACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/LogViewerACLTest.java index 96ea5c92b3..7d94ee27ad 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/LogViewerACLTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/LogViewerACLTest.java @@ -22,7 +22,6 @@ package org.apache.qpid.systest.rest.acl; import java.io.IOException; -import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.management.plugin.HttpManagement; import org.apache.qpid.server.security.acl.AbstractACLTestCase; import org.apache.qpid.systest.rest.QpidRestTestCase; @@ -34,7 +33,7 @@ public class LogViewerACLTest extends QpidRestTestCase private static final String DENIED_USER = "user2"; @Override - protected void customizeConfiguration() throws ConfigurationException, IOException + protected void customizeConfiguration() throws IOException { super.customizeConfiguration(); getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/QueueRestACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/QueueRestACLTest.java index b187ca955a..52f70a5dd2 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/QueueRestACLTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/QueueRestACLTest.java @@ -25,7 +25,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.management.plugin.HttpManagement; import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.security.acl.AbstractACLTestCase; @@ -38,7 +37,7 @@ public class QueueRestACLTest extends QpidRestTestCase private static final String DENIED_USER = "user2"; @Override - protected void customizeConfiguration() throws ConfigurationException, IOException + protected void customizeConfiguration() throws IOException { super.customizeConfiguration(); getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserPreferencesRestACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserPreferencesRestACLTest.java index 6ed84ac95a..b23e44a4d3 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserPreferencesRestACLTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserPreferencesRestACLTest.java @@ -28,7 +28,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.management.plugin.HttpManagement; import org.apache.qpid.server.model.PreferencesProvider; import org.apache.qpid.server.model.adapter.FileSystemPreferencesProvider; @@ -72,7 +71,7 @@ public class UserPreferencesRestACLTest extends QpidRestTestCase } @Override - protected void customizeConfiguration() throws ConfigurationException, IOException + protected void customizeConfiguration() throws IOException { super.customizeConfiguration(); getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java index 4c4e219695..d2f0401db5 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java @@ -28,7 +28,6 @@ import java.util.Properties; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.management.plugin.HttpManagement; import org.apache.qpid.server.security.acl.AbstractACLTestCase; import org.apache.qpid.systest.rest.QpidRestTestCase; @@ -60,7 +59,7 @@ public class UserRestACLTest extends QpidRestTestCase } @Override - protected void customizeConfiguration() throws ConfigurationException, IOException + protected void customizeConfiguration() throws IOException { super.customizeConfiguration(); getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_MANAGEMENT, HttpManagement.HTTP_BASIC_AUTHENTICATION_ENABLED, true); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java index bd826259bc..ee3a8c7260 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java @@ -22,7 +22,6 @@ package org.apache.qpid.test.client.destination; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.apache.qpid.client.AMQAnyDestination; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQDestination; @@ -31,13 +30,15 @@ import org.apache.qpid.client.AMQSession_0_10; import org.apache.qpid.client.message.QpidMessageProperties; import org.apache.qpid.jndi.PropertiesFileInitialContextFactory; import org.apache.qpid.messaging.Address; +import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.test.utils.TestBrokerConfiguration; import org.apache.qpid.transport.ExecutionErrorCode; import javax.jms.*; import javax.naming.Context; import javax.naming.InitialContext; -import java.util.Collections; + import java.util.Enumeration; import java.util.HashMap; import java.util.Hashtable; @@ -53,6 +54,9 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase @Override public void setUp() throws Exception { + TestBrokerConfiguration config = getBrokerConfiguration(); + config.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST, VirtualHost.QUEUE_MAXIMUM_DELIVERY_ATTEMPTS, 0); + super.setUp(); _connection = getConnection() ; _connection.start(); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java index 74afbf7903..4026b7a6cb 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java @@ -20,11 +20,8 @@ */ package org.apache.qpid.test.client.timeouts; -import org.apache.qpid.server.virtualhost.StandardVirtualHostFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.test.utils.QpidBrokerTestCase; +import java.util.HashMap; +import java.util.Map; import javax.jms.Connection; import javax.jms.JMSException; @@ -34,6 +31,14 @@ import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.SlowMessageStore; +import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.test.utils.TestBrokerConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * This tests that when the commit takes a long time(due to POST_COMMIT_DELAY) that the commit does not timeout * This test must be run in conjunction with SyncWaiteTimeoutDelay or be run with POST_COMMIT_DELAY > 30s to ensure @@ -43,7 +48,6 @@ public class SyncWaitDelayTest extends QpidBrokerTestCase { protected static final Logger _logger = LoggerFactory.getLogger(SyncWaitDelayTest.class); - private String VIRTUALHOST = "test"; protected long POST_COMMIT_DELAY = 1000L; protected long SYNC_WRITE_TIMEOUT = POST_COMMIT_DELAY + 1000; @@ -54,11 +58,15 @@ public class SyncWaitDelayTest extends QpidBrokerTestCase public void setUp() throws Exception { + Map<String, Object> slowMessageStoreDelays = new HashMap<String,Object>(); + slowMessageStoreDelays.put("postcommitTran", POST_COMMIT_DELAY); + + Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); + messageStoreSettings.put(MessageStore.STORE_TYPE, SlowMessageStore.TYPE); + messageStoreSettings.put(SlowMessageStore.DELAYS, slowMessageStoreDelays); - final String prefix = "virtualhosts.virtualhost." + VIRTUALHOST; - setVirtualHostConfigurationProperty(prefix + ".type", StandardVirtualHostFactory.TYPE); - setVirtualHostConfigurationProperty(prefix + ".store.class", org.apache.qpid.server.store.SlowMessageStore.class.getName()); - setVirtualHostConfigurationProperty(prefix + ".store.delays.commitTran.post", String.valueOf(POST_COMMIT_DELAY)); + TestBrokerConfiguration config = getBrokerConfiguration(); + config.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST, VirtualHost.MESSAGE_STORE_SETTINGS, messageStoreSettings); super.setUp(); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java index 6473a77855..6909a3cbbf 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java @@ -21,15 +21,16 @@ package org.apache.qpid.test.unit.client; import org.apache.log4j.Logger; - import org.apache.qpid.AMQException; import org.apache.qpid.client.AMQDestination; import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.AMQSession; import org.apache.qpid.client.RejectBehaviour; import org.apache.qpid.configuration.ClientProperties; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.test.utils.TestBrokerConfiguration; import javax.jms.Connection; import javax.jms.Destination; @@ -41,6 +42,7 @@ import javax.jms.MessageProducer; import javax.jms.Session; import javax.jms.TextMessage; import javax.jms.Topic; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -75,13 +77,13 @@ public class MaxDeliveryCountTest extends QpidBrokerTestCase public void setUp() throws Exception { //enable DLQ/maximumDeliveryCount support for all queues at the vhost level - setVirtualHostConfigurationProperty("virtualhosts.virtualhost.test.queues.maximumDeliveryCount", - String.valueOf(MAX_DELIVERY_COUNT)); - setVirtualHostConfigurationProperty("virtualhosts.virtualhost.test.queues.deadLetterQueues", - String.valueOf(true)); + + TestBrokerConfiguration brokerConfiguration = getBrokerConfiguration(); + brokerConfiguration.setBrokerAttribute(Broker.QUEUE_DEAD_LETTER_QUEUE_ENABLED, true); + brokerConfiguration.setBrokerAttribute(Broker.QUEUE_MAXIMUM_DELIVERY_ATTEMPTS, MAX_DELIVERY_COUNT); //Ensure management is on - getBrokerConfiguration().addJmxManagementConfiguration(); + brokerConfiguration.addJmxManagementConfiguration(); // Set client-side flag to allow the server to determine if messages // dead-lettered or requeued. diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutDisabledTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutDisabledTest.java index d93c7a2e71..2b914393f2 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutDisabledTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutDisabledTest.java @@ -20,6 +20,9 @@ */ package org.apache.qpid.test.unit.transacted; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.test.utils.TestBrokerConfiguration; + /** * This verifies that the default behaviour is not to time out transactions. */ @@ -29,7 +32,8 @@ public class TransactionTimeoutDisabledTest extends TransactionTimeoutTestCase protected void configure() throws Exception { // Setup housekeeping every second - setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.checkPeriod", "100"); + TestBrokerConfiguration brokerConfiguration = getBrokerConfiguration(); + brokerConfiguration.setBrokerAttribute(Broker.VIRTUALHOST_HOUSEKEEPING_CHECK_PERIOD, 100); // No transaction timeout configuration. } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTest.java index f5a234163d..366cf11c4e 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTest.java @@ -27,6 +27,7 @@ import javax.jms.MessageProducer; import javax.jms.Queue; import org.apache.qpid.server.model.Broker; +import org.apache.qpid.test.utils.TestBrokerConfiguration; /** * This tests the behaviour of transactional sessions when the {@code transactionTimeout} configuration @@ -45,28 +46,29 @@ public class TransactionTimeoutTest extends TransactionTimeoutTestCase getBrokerConfiguration().setBrokerAttribute(Broker.CONNECTION_CLOSE_WHEN_NO_ROUTE, false); // Setup housekeeping every 100ms - setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.checkPeriod", "100"); + TestBrokerConfiguration brokerConfiguration = getBrokerConfiguration(); + brokerConfiguration.setBrokerAttribute(Broker.VIRTUALHOST_HOUSEKEEPING_CHECK_PERIOD, 100); if (getName().contains("ProducerIdle")) { - setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openWarn", "0"); - setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openClose", "0"); - setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleWarn", "500"); - setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleClose", "1500"); + brokerConfiguration.setBrokerAttribute(Broker.VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_WARN, 0); + brokerConfiguration.setBrokerAttribute(Broker.VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE, 0); + brokerConfiguration.setBrokerAttribute(Broker.VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_WARN, 500); + brokerConfiguration.setBrokerAttribute(Broker.VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE, 1500); } else if (getName().contains("ProducerOpen")) { - setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openWarn", "1000"); - setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openClose", "2000"); - setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleWarn", "0"); - setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleClose", "0"); + brokerConfiguration.setBrokerAttribute(Broker.VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_WARN, 1000); + brokerConfiguration.setBrokerAttribute(Broker.VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE, 2000); + brokerConfiguration.setBrokerAttribute(Broker.VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_WARN, 0); + brokerConfiguration.setBrokerAttribute(Broker.VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE, 0); } else { - setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openWarn", "1000"); - setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openClose", "2000"); - setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleWarn", "500"); - setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleClose", "1000"); + brokerConfiguration.setBrokerAttribute(Broker.VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_WARN, 1000); + brokerConfiguration.setBrokerAttribute(Broker.VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE, 2000); + brokerConfiguration.setBrokerAttribute(Broker.VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_WARN, 500); + brokerConfiguration.setBrokerAttribute(Broker.VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE, 1500); } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java index 91dcf48001..93cf90829d 100755 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java @@ -22,7 +22,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -48,8 +47,6 @@ import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; @@ -66,10 +63,10 @@ import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.plugin.MessageStoreFactory; import org.apache.qpid.server.protocol.AmqpProtocolVersion; -import org.apache.qpid.server.store.MessageStoreConstants; -import org.apache.qpid.server.store.MessageStoreCreator; +import org.apache.qpid.server.store.MemoryMessageStore; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.virtualhost.StandardVirtualHostFactory; import org.apache.qpid.url.URLSyntaxException; import org.apache.qpid.util.FileUtils; import org.apache.qpid.util.SystemUtils; @@ -101,15 +98,12 @@ public class QpidBrokerTestCase extends QpidTestCase private Map<String, String> _propertiesSetForBroker = new HashMap<String, String>(); private Map<Integer, TestBrokerConfiguration> _brokerConfigurations; - private XMLConfiguration _testVirtualhosts = new XMLConfiguration(); protected static final String INDEX = "index"; protected static final String CONTENT = "content"; private static final String DEFAULT_INITIAL_CONTEXT = "org.apache.qpid.jndi.PropertiesFileInitialContextFactory"; - private static Map<String, String> supportedStoresClassToTypeMapping = new HashMap<String, String>(); - static { String initialContext = System.getProperty(Context.INITIAL_CONTEXT_FACTORY); @@ -118,17 +112,9 @@ public class QpidBrokerTestCase extends QpidTestCase { System.setProperty(Context.INITIAL_CONTEXT_FACTORY, DEFAULT_INITIAL_CONTEXT); } - - MessageStoreCreator messageStoreCreator = new MessageStoreCreator(); - Collection<MessageStoreFactory> factories = messageStoreCreator.getFactories(); - for (MessageStoreFactory messageStoreFactory : factories) - { - supportedStoresClassToTypeMapping.put(messageStoreFactory.createMessageStore().getClass().getName(), messageStoreFactory.getType()); - } } // system properties - private static final String TEST_VIRTUALHOSTS = "test.virtualhosts"; private static final String BROKER_LANGUAGE = "broker.language"; protected static final String BROKER_TYPE = "broker.type"; private static final String BROKER_COMMAND = "broker.command"; @@ -249,7 +235,16 @@ public class QpidBrokerTestCase extends QpidTestCase configuration.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT, Port.PORT, actualPort); configuration.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_RMI_PORT, Port.PORT, getManagementPort(actualPort)); configuration.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_JMX_PORT, Port.PORT, getManagementPort(actualPort) + JMXPORT_CONNECTORSERVER_OFFSET); + + String workDir = System.getProperty("QPID_WORK") + File.separator + TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST + File.separator + actualPort; + Map<String, Object> virtualHostSettings = configuration.getObjectAttributes(TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST); + + @SuppressWarnings("unchecked") + Map<String, Object> storeSettings = (Map<String, Object>)virtualHostSettings.get(VirtualHost.MESSAGE_STORE_SETTINGS); + storeSettings.put(MessageStore.STORE_PATH, workDir); + configuration.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST, VirtualHost.MESSAGE_STORE_SETTINGS, storeSettings); } + return configuration; } @@ -420,7 +415,7 @@ public class QpidBrokerTestCase extends QpidTestCase { int actualPort = getPort(port); TestBrokerConfiguration configuration = getBrokerConfiguration(actualPort); - startBroker(actualPort, configuration, _testVirtualhosts, managementMode); + startBroker(actualPort, configuration, managementMode); } protected File getBrokerCommandLog4JFile() @@ -434,16 +429,14 @@ public class QpidBrokerTestCase extends QpidTestCase _logger.info("Modified log config file to: " + file); } - public void startBroker(int port, TestBrokerConfiguration testConfiguration, XMLConfiguration virtualHosts) throws Exception + public void startBroker(int port, TestBrokerConfiguration testConfiguration) throws Exception { - startBroker(port, testConfiguration, virtualHosts, false); + startBroker(port, testConfiguration, false); } - public void startBroker(int port, TestBrokerConfiguration testConfiguration, XMLConfiguration virtualHosts, boolean managementMode) throws Exception + public void startBroker(int port, TestBrokerConfiguration testConfiguration, boolean managementMode) throws Exception { port = getPort(port); - String testConfig = saveTestConfiguration(port, testConfiguration); - String virtualHostsConfig = saveTestVirtualhosts(port, virtualHosts); if(_brokers.get(port) != null) { @@ -451,11 +444,10 @@ public class QpidBrokerTestCase extends QpidTestCase } Set<Integer> portsUsedByBroker = guessAllPortsUsedByBroker(port); + String testConfig = saveTestConfiguration(port, testConfiguration); if (_brokerType.equals(BrokerType.INTERNAL) && !existingInternalBroker()) { - _logger.info("Set test.virtualhosts property to: " + virtualHostsConfig); - setSystemProperty(TEST_VIRTUALHOSTS, virtualHostsConfig); setSystemProperty(BrokerProperties.PROPERTY_USE_CUSTOM_RMI_SOCKET_FACTORY, "false"); BrokerOptions options = new BrokerOptions(); @@ -549,7 +541,6 @@ public class QpidBrokerTestCase extends QpidTestCase setSystemProperty("root.logging.level"); setSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_EXCLUDES); setSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_INCLUDES); - setSystemProperty(TEST_VIRTUALHOSTS, virtualHostsConfig); // Add all the specified system properties to QPID_OPTS if (!_propertiesSetForBroker.isEmpty()) @@ -656,20 +647,6 @@ public class QpidBrokerTestCase extends QpidTestCase return _output + File.separator + getTestQueueName() + "-" + port + "-virtualhosts.xml"; } - private String relativeToQpidHome(String file) - { - _logger.debug("Converting path to be relative to QPID_HOME: " + file); - - final String qpidHome = System.getProperty(QPID_HOME,"QPID_HOME"); - _logger.debug("QPID_HOME is: " + qpidHome); - - if(!file.startsWith(qpidHome)) { - throw new RuntimeException("Provided path is not a child of the QPID_HOME directory: " + qpidHome); - } - - return file.replace(qpidHome + File.separator,""); - } - protected String getPathRelativeToWorkingDirectory(String file) { File configLocation = new File(file); @@ -715,23 +692,6 @@ public class QpidBrokerTestCase extends QpidTestCase return relative; } - protected String saveTestVirtualhosts(int port, XMLConfiguration virtualHostConfiguration) throws ConfigurationException - { - // Specify the test virtualhosts file - String testVirtualhosts = getTestVirtualhostsFile(port); - String relative = relativeToQpidHome(testVirtualhosts); - - _logger.info("Path to virtualhosts configuration: " + testVirtualhosts); - - // Create the file if configuration does not exist - if (virtualHostConfiguration.isEmpty()) - { - virtualHostConfiguration.addProperty("__ignore", "true"); - } - virtualHostConfiguration.save(testVirtualhosts); - return relative; - } - protected void cleanBrokerWork(final String qpidWork) { if (qpidWork != null) @@ -872,68 +832,34 @@ public class QpidBrokerTestCase extends QpidTestCase * Creates a new virtual host within the test virtualhost file. * @param brokerPort broker port * @param virtualHostName virtual host name - * - * @throws ConfigurationException */ - protected void createTestVirtualHost(int brokerPort, String virtualHostName) throws ConfigurationException + protected void createTestVirtualHost(int brokerPort, String virtualHostName) { - String storeClassName = getTestProfileMessageStoreClassName(); - - _testVirtualhosts.setProperty("virtualhost.name(-1)", virtualHostName); - _testVirtualhosts.setProperty("virtualhost." + virtualHostName + ".store.class", storeClassName); - + String storeType = getTestProfileMessageStoreType(); String storeDir = null; if (System.getProperty("profile", "").startsWith("java-dby-mem")) { storeDir = ":memory:"; } - else if (!MEMORY_STORE_CLASS_NAME.equals(storeClassName)) + else if (!MemoryMessageStore.TYPE.equals(storeType)) { - storeDir = "${QPID_WORK}" + File.separator + virtualHostName + "-store"; - } - - if (storeDir != null) - { - _testVirtualhosts.setProperty("virtualhost." + virtualHostName + ".store." + MessageStoreConstants.ENVIRONMENT_PATH_PROPERTY, storeDir); + storeDir = "${QPID_WORK}" + File.separator + virtualHostName + File.separator + brokerPort; } // add new virtual host configuration to the broker store Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(VirtualHost.NAME, virtualHostName); - attributes.put(VirtualHost.CONFIG_PATH, System.getProperty("broker.virtualhosts-config")); + attributes.put(VirtualHost.TYPE, StandardVirtualHostFactory.TYPE); + Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); + messageStoreSettings.put(MessageStore.STORE_TYPE, storeType); + messageStoreSettings.put(MessageStore.STORE_PATH, storeDir); + attributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, messageStoreSettings ); int port = getPort(brokerPort); getBrokerConfiguration(port).addVirtualHostConfiguration(attributes); } /** - * Set a configuration Property for this test run. - * - * This creates a new configuration based on the current configuration - * with the specified property change. - * - * Multiple calls to this method will result in multiple temporary - * configuration files being created. - * - * @param property the configuration property to set - * @param value the new value - * - * @throws ConfigurationException when loading the current config file - */ - public void setVirtualHostConfigurationProperty(String property, String value) throws ConfigurationException - { - // Choose which file to write the property to based on prefix. - if (property.startsWith("virtualhosts")) - { - _testVirtualhosts.setProperty(StringUtils.substringAfter(property, "virtualhosts."), value); - } - else - { - throw new ConfigurationException("Cannot set broker configuration as property"); - } - } - - /** * Set a System property that is to be applied only to the external test * broker. * @@ -1468,24 +1394,4 @@ public class QpidBrokerTestCase extends QpidTestCase return FAILING_PORT; } - public XMLConfiguration getTestVirtualhosts() - { - return _testVirtualhosts; - } - - public void setTestVirtualhosts(XMLConfiguration testVirtualhosts) - { - _testVirtualhosts = testVirtualhosts; - } - - public String getTestProfileMessageStoreType() - { - final String storeClass = getTestProfileMessageStoreClassName(); - /* if (storeClass == null) - { - return "Memory"; - }*/ - return supportedStoresClassToTypeMapping.get(storeClass); - } - } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java index 9e893bb7bb..31a650baad 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.test.utils; +import java.io.ByteArrayOutputStream; import java.io.File; import java.util.Collection; import java.util.Collections; @@ -45,6 +46,7 @@ import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.plugin.PluginFactory; import org.apache.qpid.server.security.access.FileAccessControlProviderConstants; import org.apache.qpid.server.security.group.FileGroupManagerFactory; +import org.apache.qpid.util.FileUtils; public class TestBrokerConfiguration { @@ -308,4 +310,8 @@ public class TestBrokerConfiguration _store.save(newAp, pp); } + public Map<String, Object> getObjectAttributes(String name) + { + return findObjectByName(name).getAttributes(); + } } diff --git a/qpid/java/systests/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory b/qpid/java/systests/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory index fdd7a904c3..9e2efc1031 100644 --- a/qpid/java/systests/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory +++ b/qpid/java/systests/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory @@ -17,3 +17,4 @@ # under the License. # org.apache.qpid.server.store.SlowMessageStoreFactory +org.apache.qpid.server.store.QuotaMessageStoreFactory diff --git a/qpid/java/test-profiles/java-bdb-spawn.0-10.testprofile b/qpid/java/test-profiles/java-bdb-spawn.0-10.testprofile index 4230888a21..f6d13586b0 100644 --- a/qpid/java/test-profiles/java-bdb-spawn.0-10.testprofile +++ b/qpid/java/test-profiles/java-bdb-spawn.0-10.testprofile @@ -25,7 +25,7 @@ broker.ready=BRK-1004 broker.stopped=Exception qpid.broker_default_amqp_protocol_excludes=AMQP_1_0 broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-bdb.xml -messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore +messagestore.type=BDB profile.excludes=JavaExcludes JavaPersistentExcludes Java010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true diff --git a/qpid/java/test-profiles/java-bdb-spawn.0-8.testprofile b/qpid/java/test-profiles/java-bdb-spawn.0-8.testprofile index 054eb9c1b6..74ee344ced 100644 --- a/qpid/java/test-profiles/java-bdb-spawn.0-8.testprofile +++ b/qpid/java/test-profiles/java-bdb-spawn.0-8.testprofile @@ -25,7 +25,7 @@ broker.ready=BRK-1004 broker.stopped=Exception qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1,AMQP_0_9 broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-bdb.xml -messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore +messagestore.type=BDB profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true @@ -34,4 +34,3 @@ broker.version=v0_8 # Do not enable. Allow client to attempt 0-10 and negotiate downwards # #qpid.amqp.version=0-8 - diff --git a/qpid/java/test-profiles/java-bdb-spawn.0-9-1.testprofile b/qpid/java/test-profiles/java-bdb-spawn.0-9-1.testprofile index 65d86d9310..c747b8703d 100644 --- a/qpid/java/test-profiles/java-bdb-spawn.0-9-1.testprofile +++ b/qpid/java/test-profiles/java-bdb-spawn.0-9-1.testprofile @@ -25,7 +25,7 @@ broker.ready=BRK-1004 broker.stopped=Exception qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10 broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-bdb.xml -messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore +messagestore.type=BDB profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true @@ -34,4 +34,3 @@ broker.version=v0_9_1 # Do not enable. Allow client to attempt 0-10 and negotiate downwards # #qpid.amqp.version=0-91 - diff --git a/qpid/java/test-profiles/java-bdb-spawn.0-9.testprofile b/qpid/java/test-profiles/java-bdb-spawn.0-9.testprofile index 4818cfff28..6d0c4be6da 100644 --- a/qpid/java/test-profiles/java-bdb-spawn.0-9.testprofile +++ b/qpid/java/test-profiles/java-bdb-spawn.0-9.testprofile @@ -25,7 +25,7 @@ broker.ready=BRK-1004 broker.stopped=Exception qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1 broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-bdb.xml -messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore +messagestore.type=BDB profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true @@ -34,4 +34,3 @@ broker.version=v0_9 # Do not enable. Allow client to attempt 0-10 and negotiate downwards # #qpid.amqp.version=0-9 - diff --git a/qpid/java/test-profiles/java-bdb.0-10.testprofile b/qpid/java/test-profiles/java-bdb.0-10.testprofile index cf5f608957..373647368f 100644 --- a/qpid/java/test-profiles/java-bdb.0-10.testprofile +++ b/qpid/java/test-profiles/java-bdb.0-10.testprofile @@ -26,7 +26,7 @@ broker.ready=BRK-1004 broker.stopped=Exception qpid.broker_default_amqp_protocol_excludes=AMQP_1_0 broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-bdb.xml -messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore +messagestore.type=BDB profile.excludes=JavaExcludes JavaPersistentExcludes Java010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true diff --git a/qpid/java/test-profiles/java-bdb.0-8.testprofile b/qpid/java/test-profiles/java-bdb.0-8.testprofile index 09270f89b0..1882d916f5 100644 --- a/qpid/java/test-profiles/java-bdb.0-8.testprofile +++ b/qpid/java/test-profiles/java-bdb.0-8.testprofile @@ -26,7 +26,7 @@ broker.ready=BRK-1004 broker.stopped=Exception qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1,AMQP_0_9 broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-bdb.xml -messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore +messagestore.type=BDB profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true @@ -35,4 +35,3 @@ broker.version=v0_8 # Do not enable. Allow client to attempt 0-10 and negotiate downwards # #qpid.amqp.version=0-8 - diff --git a/qpid/java/test-profiles/java-bdb.0-9-1.testprofile b/qpid/java/test-profiles/java-bdb.0-9-1.testprofile index 4248a55f1c..36ec86f833 100644 --- a/qpid/java/test-profiles/java-bdb.0-9-1.testprofile +++ b/qpid/java/test-profiles/java-bdb.0-9-1.testprofile @@ -25,8 +25,7 @@ broker.command.windows=build${file.separator}bin${file.separator}qpid-server.bat broker.ready=BRK-1004 broker.stopped=Exception qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10 -broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-bdb.xml -messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore +messagestore.type=BDB profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true @@ -35,4 +34,3 @@ broker.version=v0_9_1 # Do not enable. Allow client to attempt 0-10 and negotiate downwards # #qpid.amqp.version=0-91 - diff --git a/qpid/java/test-profiles/java-bdb.0-9.testprofile b/qpid/java/test-profiles/java-bdb.0-9.testprofile index cff55d7bde..b493181894 100644 --- a/qpid/java/test-profiles/java-bdb.0-9.testprofile +++ b/qpid/java/test-profiles/java-bdb.0-9.testprofile @@ -25,8 +25,7 @@ broker.command.windows=build${file.separator}bin${file.separator}qpid-server.bat broker.ready=BRK-1004 broker.stopped=Exception qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1 -broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-bdb.xml -messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore +messagestore.type=BDB profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true @@ -35,4 +34,3 @@ broker.version=v0_9 # Do not enable. Allow client to attempt 0-10 and negotiate downwards # #qpid.amqp.version=0-9 - diff --git a/qpid/java/test-profiles/java-dby-mem.0-10.testprofile b/qpid/java/test-profiles/java-dby-mem.0-10.testprofile index f968d58ec9..196eccb366 100644 --- a/qpid/java/test-profiles/java-dby-mem.0-10.testprofile +++ b/qpid/java/test-profiles/java-dby-mem.0-10.testprofile @@ -26,7 +26,7 @@ broker.ready=BRK-1004 broker.stopped=Exception qpid.broker_default_amqp_protocol_excludes=AMQP_1_0 broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby-mem.xml -messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore +messagestore.type=DERBY profile.excludes=JavaPersistentExcludes JavaDerbyExcludes Java010Excludes broker.clean.between.tests=true broker.persistent=true diff --git a/qpid/java/test-profiles/java-dby-mem.0-8.testprofile b/qpid/java/test-profiles/java-dby-mem.0-8.testprofile index b50e17b955..670d8d1f3e 100644 --- a/qpid/java/test-profiles/java-dby-mem.0-8.testprofile +++ b/qpid/java/test-profiles/java-dby-mem.0-8.testprofile @@ -26,7 +26,7 @@ broker.ready=BRK-1004 broker.stopped=Exception qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1,AMQP_0_9 broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby-mem.xml -messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore +messagestore.type=DERBY profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true broker.persistent=true @@ -34,4 +34,3 @@ broker.persistent=true # Do not enable. Allow client to attempt 0-10 and negotiate downwards # #qpid.amqp.version=0-8 - diff --git a/qpid/java/test-profiles/java-dby-mem.0-9-1.testprofile b/qpid/java/test-profiles/java-dby-mem.0-9-1.testprofile index d16d17d220..2f345a8fb5 100644 --- a/qpid/java/test-profiles/java-dby-mem.0-9-1.testprofile +++ b/qpid/java/test-profiles/java-dby-mem.0-9-1.testprofile @@ -26,7 +26,7 @@ broker.ready=BRK-1004 broker.stopped=Exception qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10 broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby-mem.xml -messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore +messagestore.type=DERBY profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true broker.persistent=true @@ -34,4 +34,3 @@ broker.persistent=true # Do not enable. Allow client to attempt 0-10 and negotiate downwards # #qpid.amqp.version=0-91 - diff --git a/qpid/java/test-profiles/java-dby-mem.0-9.testprofile b/qpid/java/test-profiles/java-dby-mem.0-9.testprofile index 35f2d0aa8c..1ffd0b1372 100644 --- a/qpid/java/test-profiles/java-dby-mem.0-9.testprofile +++ b/qpid/java/test-profiles/java-dby-mem.0-9.testprofile @@ -26,7 +26,7 @@ broker.ready=BRK-1004 broker.stopped=Exception qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1 broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby-mem.xml -messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore +messagestore.type=DERBY profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true broker.persistent=true @@ -34,4 +34,3 @@ broker.persistent=true # Do not enable. Allow client to attempt 0-10 and negotiate downwards # #qpid.amqp.version=0-9 - diff --git a/qpid/java/test-profiles/java-dby-spawn.0-10.testprofile b/qpid/java/test-profiles/java-dby-spawn.0-10.testprofile index a3ea69a1ee..325e84adeb 100644 --- a/qpid/java/test-profiles/java-dby-spawn.0-10.testprofile +++ b/qpid/java/test-profiles/java-dby-spawn.0-10.testprofile @@ -25,7 +25,7 @@ broker.ready=BRK-1004 broker.stopped=Exception qpid.broker_default_amqp_protocol_excludes=AMQP_1_0 broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby.xml -messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore +messagestore.type=DERBY profile.excludes=JavaPersistentExcludes JavaDerbyExcludes Java010Excludes broker.clean.between.tests=true broker.persistent=true diff --git a/qpid/java/test-profiles/java-dby-spawn.0-8.testprofile b/qpid/java/test-profiles/java-dby-spawn.0-8.testprofile index 8e737cec7c..22a293645c 100644 --- a/qpid/java/test-profiles/java-dby-spawn.0-8.testprofile +++ b/qpid/java/test-profiles/java-dby-spawn.0-8.testprofile @@ -25,7 +25,7 @@ broker.ready=BRK-1004 broker.stopped=Exception qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1,AMQP_0_9 broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby.xml -messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore +messagestore.type=DERBY profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true broker.persistent=true @@ -33,4 +33,3 @@ broker.persistent=true # Do not enable. Allow client to attempt 0-10 and negotiate downwards # #qpid.amqp.version=0-8 - diff --git a/qpid/java/test-profiles/java-dby-spawn.0-9-1.testprofile b/qpid/java/test-profiles/java-dby-spawn.0-9-1.testprofile index 9de7a4a490..ac4b71058c 100644 --- a/qpid/java/test-profiles/java-dby-spawn.0-9-1.testprofile +++ b/qpid/java/test-profiles/java-dby-spawn.0-9-1.testprofile @@ -25,7 +25,7 @@ broker.ready=BRK-1004 broker.stopped=Exception qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10 broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby.xml -messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore +messagestore.type=DERBY profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true broker.persistent=true @@ -33,4 +33,3 @@ broker.persistent=true # Do not enable. Allow client to attempt 0-10 and negotiate downwards # #qpid.amqp.version=0-91 - diff --git a/qpid/java/test-profiles/java-dby-spawn.0-9.testprofile b/qpid/java/test-profiles/java-dby-spawn.0-9.testprofile index 97fff81068..5d68fc5a52 100644 --- a/qpid/java/test-profiles/java-dby-spawn.0-9.testprofile +++ b/qpid/java/test-profiles/java-dby-spawn.0-9.testprofile @@ -25,7 +25,7 @@ broker.ready=BRK-1004 broker.stopped=Exception qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1 broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby.xml -messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore +messagestore.type=DERBY profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true broker.persistent=true @@ -33,4 +33,3 @@ broker.persistent=true # Do not enable. Allow client to attempt 0-10 and negotiate downwards # #qpid.amqp.version=0-9 - diff --git a/qpid/java/test-profiles/java-dby.0-10.testprofile b/qpid/java/test-profiles/java-dby.0-10.testprofile index 07d75577d3..d850594c1d 100644 --- a/qpid/java/test-profiles/java-dby.0-10.testprofile +++ b/qpid/java/test-profiles/java-dby.0-10.testprofile @@ -26,7 +26,7 @@ broker.ready=BRK-1004 broker.stopped=Exception qpid.broker_default_amqp_protocol_excludes=AMQP_1_0 broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby.xml -messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore +messagestore.type=DERBY profile.excludes=JavaPersistentExcludes JavaDerbyExcludes Java010Excludes broker.clean.between.tests=true broker.persistent=true diff --git a/qpid/java/test-profiles/java-dby.0-8.testprofile b/qpid/java/test-profiles/java-dby.0-8.testprofile index b24dc8381d..f296126aaf 100644 --- a/qpid/java/test-profiles/java-dby.0-8.testprofile +++ b/qpid/java/test-profiles/java-dby.0-8.testprofile @@ -26,7 +26,7 @@ broker.ready=BRK-1004 broker.stopped=Exception qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1,AMQP_0_9 broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby.xml -messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore +messagestore.type=DERBY profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true broker.persistent=true @@ -34,4 +34,3 @@ broker.persistent=true # Do not enable. Allow client to attempt 0-10 and negotiate downwards # #qpid.amqp.version=0-8 - diff --git a/qpid/java/test-profiles/java-dby.0-9-1.testprofile b/qpid/java/test-profiles/java-dby.0-9-1.testprofile index ec08913626..5cb5e27937 100644 --- a/qpid/java/test-profiles/java-dby.0-9-1.testprofile +++ b/qpid/java/test-profiles/java-dby.0-9-1.testprofile @@ -26,7 +26,7 @@ broker.ready=BRK-1004 broker.stopped=Exception qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10 broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby.xml -messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore +messagestore.type=DERBY profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true broker.persistent=true @@ -34,4 +34,3 @@ broker.persistent=true # Do not enable. Allow client to attempt 0-10 and negotiate downwards # #qpid.amqp.version=0-91 - diff --git a/qpid/java/test-profiles/java-dby.0-9.testprofile b/qpid/java/test-profiles/java-dby.0-9.testprofile index 73b1161f6b..9314e3e9ee 100644 --- a/qpid/java/test-profiles/java-dby.0-9.testprofile +++ b/qpid/java/test-profiles/java-dby.0-9.testprofile @@ -26,7 +26,7 @@ broker.ready=BRK-1004 broker.stopped=Exception qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1 broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby.xml -messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore +messagestore.type=DERBY profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true broker.persistent=true @@ -34,4 +34,3 @@ broker.persistent=true # Do not enable. Allow client to attempt 0-10 and negotiate downwards # #qpid.amqp.version=0-9 - diff --git a/qpid/java/test-profiles/testprofile.defaults b/qpid/java/test-profiles/testprofile.defaults index ccd31a5d1e..93f3c20541 100644 --- a/qpid/java/test-profiles/testprofile.defaults +++ b/qpid/java/test-profiles/testprofile.defaults @@ -21,7 +21,7 @@ java.naming.provider.url=${test.profiles}${file.separator}test-provider.properti broker.ready=Listening on TCP broker.config=build/etc/config-systests.json -messagestore.class.name=org.apache.qpid.server.store.MemoryMessageStore +messagestore.type=Memory broker.protocol.excludes= broker.persistent=false @@ -63,6 +63,6 @@ exclude.modules=none profile.clustered=false broker.config-store-type=json -broker.virtualhosts-config="${QPID_HOME}${file.separator}etc${file.separator}virtualhosts-systests.xml" + |