diff options
Diffstat (limited to 'qpid/java/bdbstore/src')
125 files changed, 0 insertions, 22226 deletions
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/logging/subjects/BDBHAVirtualHostNodeLogSubject.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/logging/subjects/BDBHAVirtualHostNodeLogSubject.java deleted file mode 100644 index a209062993..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/logging/subjects/BDBHAVirtualHostNodeLogSubject.java +++ /dev/null @@ -1,32 +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.logging.subjects; - - -public class BDBHAVirtualHostNodeLogSubject extends AbstractLogSubject -{ - public static final String VIRTUAL_HOST_NODE_FORMAT = "grp(/{0})/vhn(/{1})"; - - public BDBHAVirtualHostNodeLogSubject(String groupName, String nodeName) - { - setLogStringWithFormat(VIRTUAL_HOST_NODE_FORMAT, groupName, nodeName); - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/logging/subjects/GroupLogSubject.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/logging/subjects/GroupLogSubject.java deleted file mode 100644 index 51fd1fc2dc..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/logging/subjects/GroupLogSubject.java +++ /dev/null @@ -1,32 +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.logging.subjects; - - -public class GroupLogSubject extends AbstractLogSubject -{ - public static final String GROUP_FORMAT = "grp(/{0})"; - - public GroupLogSubject(String groupName) - { - setLogStringWithFormat(GROUP_FORMAT, groupName); - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AMQShortStringEncoding.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AMQShortStringEncoding.java deleted file mode 100644 index 2186597380..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AMQShortStringEncoding.java +++ /dev/null @@ -1,63 +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.TupleInput; -import com.sleepycat.bind.tuple.TupleOutput; - -import org.apache.qpid.framing.AMQShortString; - -public class AMQShortStringEncoding -{ - private AMQShortStringEncoding() - { - } - - public static AMQShortString readShortString(TupleInput tupleInput) - { - int length = tupleInput.readShort(); - if (length < 0) - { - return null; - } - else - { - byte[] stringBytes = new byte[length]; - tupleInput.readFast(stringBytes); - return new AMQShortString(stringBytes); - } - - } - - public static void writeShortString(AMQShortString shortString, TupleOutput tupleOutput) - { - - if (shortString == null) - { - tupleOutput.writeShort(-1); - } - else - { - tupleOutput.writeShort(shortString.length()); - tupleOutput.writeFast(shortString.getBytes(), 0, shortString.length()); - } - } -} 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 b030b6c091..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java +++ /dev/null @@ -1,1675 +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 static org.apache.qpid.server.store.berkeleydb.BDBUtils.DEFAULT_DATABASE_CONFIG; -import static org.apache.qpid.server.store.berkeleydb.BDBUtils.abortTransactionSafely; -import static org.apache.qpid.server.store.berkeleydb.BDBUtils.closeCursorSafely; - -import java.lang.ref.SoftReference; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Random; -import java.util.UUID; - -import com.sleepycat.bind.tuple.ByteBinding; -import com.sleepycat.bind.tuple.LongBinding; -import com.sleepycat.je.Cursor; -import com.sleepycat.je.Database; -import com.sleepycat.je.DatabaseEntry; -import com.sleepycat.je.LockConflictException; -import com.sleepycat.je.LockMode; -import com.sleepycat.je.OperationStatus; -import com.sleepycat.je.Sequence; -import com.sleepycat.je.SequenceConfig; -import com.sleepycat.je.Transaction; -import org.slf4j.Logger; - -import org.apache.qpid.server.message.EnqueueableMessage; -import org.apache.qpid.server.model.ConfiguredObject; -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.MessageEnqueueRecord; -import org.apache.qpid.server.store.MessageHandle; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.StorableMessageMetaData; -import org.apache.qpid.server.store.StoreException; -import org.apache.qpid.server.util.FutureResult; -import org.apache.qpid.server.store.StoredMessage; -import org.apache.qpid.server.store.TransactionLogResource; -import org.apache.qpid.server.store.Xid; -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.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.XidBinding; -import org.apache.qpid.server.store.berkeleydb.upgrade.Upgrader; -import org.apache.qpid.server.store.handler.DistributedTransactionHandler; -import org.apache.qpid.server.store.handler.MessageHandler; -import org.apache.qpid.server.store.handler.MessageInstanceHandler; - - -public abstract class AbstractBDBMessageStore implements MessageStore -{ - - private static final int LOCK_RETRY_ATTEMPTS = 5; - - private static final String MESSAGE_META_DATA_DB_NAME = "MESSAGE_METADATA"; - private static final String MESSAGE_META_DATA_SEQ_DB_NAME = "MESSAGE_METADATA.SEQ"; - private static final String MESSAGE_CONTENT_DB_NAME = "MESSAGE_CONTENT"; - private static final String DELIVERY_DB_NAME = "QUEUE_ENTRIES"; - - //TODO: Add upgrader to remove BRIDGES and LINKS - private static final String BRIDGEDB_NAME = "BRIDGES"; - private static final String LINKDB_NAME = "LINKS"; - private static final String XID_DB_NAME = "XIDS"; - - private final EventManager _eventManager = new EventManager(); - - private final DatabaseEntry MESSAGE_METADATA_SEQ_KEY = new DatabaseEntry("MESSAGE_METADATA_SEQ_KEY".getBytes( - Charset.forName("UTF-8"))); - - private final SequenceConfig MESSAGE_METADATA_SEQ_CONFIG = SequenceConfig.DEFAULT. - setAllowCreate(true). - setInitialValue(1). - setWrap(true). - setCacheSize(100000); - - private boolean _limitBusted; - private long _totalStoreSize; - - @Override - public void upgradeStoreStructure() throws StoreException - { - try - { - new Upgrader(getEnvironmentFacade().getEnvironment(), getParent()).upgradeIfNecessary(); - } - catch(RuntimeException e) - { - throw getEnvironmentFacade().handleDatabaseException("Cannot upgrade store", e); - } - - // TODO this relies on the fact that the VH will call upgrade just before putting the VH into service. - _totalStoreSize = getSizeOnDisk(); - } - - @Override - public <T extends StorableMessageMetaData> MessageHandle<T> addMessage(T metaData) - { - - long newMessageId = getNextMessageId(); - - return new StoredBDBMessage<T>(newMessageId, metaData); - } - - public long getNextMessageId() - { - long newMessageId; - try - { - // The implementations of sequences mean that there is only a transaction - // after every n sequence values, where n is the MESSAGE_METADATA_SEQ_CONFIG.getCacheSize() - - Sequence mmdSeq = getEnvironmentFacade().openSequence(getMessageMetaDataSeqDb(), - MESSAGE_METADATA_SEQ_KEY, - MESSAGE_METADATA_SEQ_CONFIG); - newMessageId = mmdSeq.get(null, 1); - } - catch (RuntimeException de) - { - throw getEnvironmentFacade().handleDatabaseException("Cannot get sequence value for new message", de); - } - return newMessageId; - } - - @Override - public boolean isPersistent() - { - return true; - } - - @Override - public org.apache.qpid.server.store.Transaction newTransaction() - { - checkMessageStoreOpen(); - - return new BDBTransaction(); - } - - @Override - public void addEventListener(final EventListener eventListener, final Event... events) - { - _eventManager.addEventListener(eventListener, events); - } - - @Override - public MessageStoreReader newMessageStoreReader() - { - return new BDBMessageStoreReader(); - } - - /** - * 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. - */ - StorableMessageMetaData getMessageMetaData(long messageId) throws StoreException - { - if (getLogger().isDebugEnabled()) - { - getLogger().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 (RuntimeException e) - { - throw getEnvironmentFacade().handleDatabaseException("Error reading message metadata for message with id " - + messageId - + ": " - + e.getMessage(), e); - } - } - - void removeMessage(long messageId, boolean sync) throws StoreException - { - boolean complete = false; - Transaction tx = null; - - Random rand = null; - int attempts = 0; - try - { - do - { - tx = null; - try - { - tx = getEnvironmentFacade().getEnvironment().beginTransaction(null, null); - - //remove the message meta data from the store - DatabaseEntry key = new DatabaseEntry(); - LongBinding.longToEntry(messageId, key); - - if (getLogger().isDebugEnabled()) - { - getLogger().debug("Removing message id " + messageId); - } - - - OperationStatus status = getMessageMetaDataDb().delete(tx, key); - if (status == OperationStatus.NOTFOUND) - { - if (getLogger().isDebugEnabled()) - { - getLogger().debug("Message id " + messageId - + " not found (attempt to remove failed - probably application initiated rollback)"); - } - } - - if (getLogger().isDebugEnabled()) - { - getLogger().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 (getLogger().isDebugEnabled()) - { - getLogger().debug("Deleted content for message " + messageId); - } - - getEnvironmentFacade().commit(tx, sync); - - complete = true; - tx = null; - } - catch (LockConflictException e) - { - try - { - if(tx != null) - { - tx.abort(); - } - } - catch(RuntimeException e2) - { - getLogger().warn( - "Unable to abort transaction after LockConflictException on removal of message with id " - + messageId, - e2); - // rethrow the original log conflict exception, the secondary exception should already have - // been logged. - throw getEnvironmentFacade().handleDatabaseException("Cannot remove message with id " - + messageId, e); - } - - - getLogger().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 getEnvironmentFacade().handleDatabaseException("Cannot remove messages", e); - } - } - } - while(!complete); - } - catch (RuntimeException e) - { - getLogger().error("Unexpected BDB exception", e); - - try - { - abortTransactionSafely(tx, - getEnvironmentFacade()); - } - finally - { - tx = null; - } - - throw getEnvironmentFacade().handleDatabaseException("Error removing message with id " - + messageId - + " from database: " - + e.getMessage(), e); - } - finally - { - try - { - abortTransactionSafely(tx, - getEnvironmentFacade()); - } - finally - { - tx = null; - } - } - } - - - /** - * 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. - */ - 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 (getLogger().isDebugEnabled()) - { - getLogger().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 (RuntimeException e) - { - throw getEnvironmentFacade().handleDatabaseException("Error getting AMQMessage with id " - + messageId - + " to database: " - + e.getMessage(), e); - } - } - - byte[] getAllContent(long messageId) throws StoreException - { - DatabaseEntry contentKeyEntry = new DatabaseEntry(); - LongBinding.longToEntry(messageId, contentKeyEntry); - DatabaseEntry value = new DatabaseEntry(); - ContentBinding contentTupleBinding = ContentBinding.getInstance(); - - - if (getLogger().isDebugEnabled()) - { - getLogger().debug("Message Id: " + messageId + " Getting content body"); - } - - try - { - - int written = 0; - OperationStatus status = getMessageContentDb().get(null, contentKeyEntry, value, LockMode.READ_UNCOMMITTED); - if (status == OperationStatus.SUCCESS) - { - return contentTupleBinding.entryToObject(value); - } - else - { - throw new StoreException("Unable to find message with id " + messageId); - } - - } - catch (RuntimeException e) - { - throw getEnvironmentFacade().handleDatabaseException("Error getting AMQMessage with id " - + messageId - + " to database: " - + e.getMessage(), e); - } - } - - private void visitMessagesInternal(MessageHandler handler, EnvironmentFacade environmentFacade) - { - Cursor cursor = null; - try - { - cursor = getMessageMetaDataDb().openCursor(null, null); - DatabaseEntry key = new DatabaseEntry(); - DatabaseEntry value = new DatabaseEntry(); - MessageMetaDataBinding valueBinding = MessageMetaDataBinding.getInstance(); - - 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); - - if (!handler.handle(message)) - { - break; - } - } - } - catch (RuntimeException e) - { - throw environmentFacade.handleDatabaseException("Cannot visit messages", e); - } - finally - { - if (cursor != null) - { - try - { - cursor.close(); - } - catch(RuntimeException e) - { - throw environmentFacade.handleDatabaseException("Cannot close cursor", e); - } - } - } - } - - - private StoredBDBMessage<?> getMessageInternal(long messageId, EnvironmentFacade environmentFacade) - { - try - { - DatabaseEntry key = new DatabaseEntry(); - DatabaseEntry value = new DatabaseEntry(); - MessageMetaDataBinding valueBinding = MessageMetaDataBinding.getInstance(); - LongBinding.longToEntry(messageId, key); - if(getMessageMetaDataDb().get(null, key, value, LockMode.READ_COMMITTED) == OperationStatus.SUCCESS) - { - StorableMessageMetaData metaData = valueBinding.entryToObject(value); - StoredBDBMessage message = new StoredBDBMessage(messageId, metaData, true); - return message; - } - else - { - return null; - } - - } - catch (RuntimeException e) - { - throw environmentFacade.handleDatabaseException("Cannot visit messages", e); - } - } - - /** - * 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. - */ - private void addContent(final 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 (getLogger().isDebugEnabled()) - { - getLogger().debug("Storing content for message " + messageId + " in transaction " + tx); - - } - } - catch (RuntimeException e) - { - throw getEnvironmentFacade().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 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 Transaction tx, long messageId, - StorableMessageMetaData messageMetaData) - throws StoreException - { - if (getLogger().isDebugEnabled()) - { - getLogger().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 (getLogger().isDebugEnabled()) - { - getLogger().debug("Storing message metadata for message id " + messageId + " in transaction " + tx); - } - } - catch (RuntimeException e) - { - throw getEnvironmentFacade().handleDatabaseException("Error writing message metadata with id " - + messageId - + " to database: " - + e.getMessage(), 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. - */ - private void enqueueMessage(final 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 (getLogger().isDebugEnabled()) - { - getLogger().debug("Enqueuing message " + messageId + " on queue " - + queue.getName() + " with id " + queue.getId() + " in transaction " + tx); - } - getDeliveryDb().put(tx, key, value); - } - catch (RuntimeException e) - { - getLogger().error("Failed to enqueue: " + e.getMessage(), e); - throw getEnvironmentFacade().handleDatabaseException("Error writing enqueued message with id " - + messageId - + " for queue " - + 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 queueId The id of 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. - */ - private void dequeueMessage(final Transaction tx, final UUID queueId, - long messageId) throws StoreException - { - - DatabaseEntry key = new DatabaseEntry(); - QueueEntryBinding keyBinding = QueueEntryBinding.getInstance(); - QueueEntryKey queueEntryKey = new QueueEntryKey(queueId, messageId); - UUID id = queueId; - keyBinding.objectToEntry(queueEntryKey, key); - if (getLogger().isDebugEnabled()) - { - getLogger().debug("Dequeue message id " + messageId + " from queue 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 with id " + id); - } - else if (status != OperationStatus.SUCCESS) - { - throw new StoreException("Unable to remove message with id " + messageId + " on queue with id " + id); - } - - if (getLogger().isDebugEnabled()) - { - getLogger().debug("Removed message " + messageId + " on queue with id " + id); - - } - } - catch (RuntimeException e) - { - - getLogger().error("Failed to dequeue message " + messageId + " in transaction " + tx, e); - - throw getEnvironmentFacade().handleDatabaseException("Error accessing database while dequeuing message: " - + e.getMessage(), e); - } - } - - private List<Runnable> recordXid(Transaction txn, - long format, - byte[] globalId, - byte[] branchId, - org.apache.qpid.server.store.Transaction.EnqueueRecord[] enqueues, - org.apache.qpid.server.store.Transaction.DequeueRecord[] 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); - List<Runnable> postActions = new ArrayList<>(); - for(org.apache.qpid.server.store.Transaction.EnqueueRecord enqueue : enqueues) - { - StoredMessage storedMessage = enqueue.getMessage().getStoredMessage(); - if(storedMessage instanceof StoredBDBMessage) - { - postActions.add(((StoredBDBMessage) storedMessage).store(txn)); - } - } - - try - { - getXidDb().put(txn, key, value); - return postActions; - } - catch (RuntimeException e) - { - getLogger().error("Failed to write xid: " + e.getMessage(), e); - throw getEnvironmentFacade().handleDatabaseException("Error writing xid to database", e); - } - } - - private void removeXid(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 (RuntimeException e) - { - - getLogger().error("Failed to remove xid in transaction " + txn, e); - - throw getEnvironmentFacade().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 org.apache.qpid.server.store.StoreException If the operation fails for any reason. - */ - private FutureResult commitTranImpl(final Transaction tx, boolean syncCommit) throws StoreException - { - if (tx == null) - { - throw new StoreException("Fatal internal error: transactional is null at commitTran"); - } - - FutureResult result = getEnvironmentFacade().commit(tx, syncCommit); - - if (getLogger().isDebugEnabled()) - { - String transactionType = syncCommit ? "synchronous" : "asynchronous"; - getLogger().debug("commitTranImpl completed " + transactionType + " transaction " + tx); - } - - 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. - */ - private void abortTran(final Transaction tx) throws StoreException - { - if (getLogger().isDebugEnabled()) - { - getLogger().debug("abortTran called for transaction " + tx); - } - - try - { - tx.abort(); - } - catch (RuntimeException e) - { - throw getEnvironmentFacade().handleDatabaseException("Error aborting transaction: " + e.getMessage(), e); - } - } - - private void storedSizeChangeOccurred(final int delta) throws StoreException - { - try - { - storedSizeChange(delta); - } - catch(RuntimeException e) - { - throw getEnvironmentFacade().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() - { - BDBUtils.runCleaner(getEnvironmentFacade().getEnvironment()); - } - - private long getSizeOnDisk() - { - return getEnvironmentFacade().getEnvironment().getStats(null).getTotalLogSize(); - } - - private Database getMessageContentDb() - { - return getEnvironmentFacade().openDatabase(MESSAGE_CONTENT_DB_NAME, DEFAULT_DATABASE_CONFIG); - } - - private Database getMessageMetaDataDb() - { - return getEnvironmentFacade().openDatabase(MESSAGE_META_DATA_DB_NAME, DEFAULT_DATABASE_CONFIG); - } - - private Database getMessageMetaDataSeqDb() - { - return getEnvironmentFacade().openDatabase(MESSAGE_META_DATA_SEQ_DB_NAME, DEFAULT_DATABASE_CONFIG); - } - - private Database getDeliveryDb() - { - return getEnvironmentFacade().openDatabase(DELIVERY_DB_NAME, DEFAULT_DATABASE_CONFIG); - } - - private Database getXidDb() - { - return getEnvironmentFacade().openDatabase(XID_DB_NAME, DEFAULT_DATABASE_CONFIG); - } - - protected abstract void checkMessageStoreOpen(); - - protected abstract ConfiguredObject<?> getParent(); - - protected abstract EnvironmentFacade getEnvironmentFacade(); - - protected abstract long getPersistentSizeLowThreshold(); - - protected abstract long getPersistentSizeHighThreshold(); - - protected abstract Logger getLogger(); - - static interface MessageDataRef<T extends StorableMessageMetaData> - { - T getMetaData(); - byte[] getData(); - void setData(byte[] data); - boolean isHardRef(); - } - - private static final class MessageDataHardRef<T extends StorableMessageMetaData> implements MessageDataRef<T> - { - private final T _metaData; - private byte[] _data; - - private MessageDataHardRef(final T metaData) - { - _metaData = metaData; - } - - @Override - public T getMetaData() - { - return _metaData; - } - - @Override - public byte[] getData() - { - return _data; - } - - @Override - public void setData(final byte[] data) - { - _data = data; - } - - @Override - public boolean isHardRef() - { - return true; - } - } - - private static final class MessageData<T extends StorableMessageMetaData> - { - private T _metaData; - private SoftReference<byte[]> _data; - - private MessageData(final T metaData, final byte[] data) - { - _metaData = metaData; - - if(data != null) - { - _data = new SoftReference<>(data); - } - } - - public T getMetaData() - { - return _metaData; - } - - public byte[] getData() - { - return _data == null ? null : _data.get(); - } - - public void setData(final byte[] data) - { - _data = new SoftReference<>(data); - } - - - } - private static final class MessageDataSoftRef<T extends StorableMessageMetaData> extends SoftReference<MessageData<T>> implements MessageDataRef<T> - { - - public MessageDataSoftRef(final T metadata, byte[] data) - { - super(new MessageData<T>(metadata, data)); - } - - @Override - public T getMetaData() - { - MessageData<T> ref = get(); - return ref == null ? null : ref.getMetaData(); - } - - @Override - public byte[] getData() - { - MessageData<T> ref = get(); - - return ref == null ? null : ref.getData(); - } - - @Override - public void setData(final byte[] data) - { - MessageData<T> ref = get(); - if(ref != null) - { - ref.setData(data); - } - } - - @Override - public boolean isHardRef() - { - return false; - } - } - - final class StoredBDBMessage<T extends StorableMessageMetaData> implements StoredMessage<T>, MessageHandle<T> - { - - private final long _messageId; - - private volatile MessageDataRef<T> _messageDataRef; - - StoredBDBMessage(long messageId, T metaData) - { - this(messageId, metaData, false); - } - - StoredBDBMessage(long messageId, T metaData, boolean isRecovered) - { - _messageId = messageId; - - if(!isRecovered) - { - _messageDataRef = new MessageDataHardRef<>(metaData); - } - else - { - _messageDataRef = new MessageDataSoftRef<>(metaData, null); - } - } - - @Override - public T getMetaData() - { - T metaData = _messageDataRef.getMetaData(); - - if(metaData == null) - { - checkMessageStoreOpen(); - metaData = (T) getMessageMetaData(_messageId); - _messageDataRef = new MessageDataSoftRef<>(metaData,null); - } - return metaData; - } - - @Override - public long getMessageNumber() - { - return _messageId; - } - - @Override - public void addContent(ByteBuffer src) - { - src = src.slice(); - byte[] data = _messageDataRef.getData(); - if(data == null) - { - data = new byte[src.remaining()]; - src.duplicate().get(data); - _messageDataRef.setData(data); - } - else - { - byte[] oldData = data; - data = new byte[oldData.length + src.remaining()]; - - - System.arraycopy(oldData, 0, data, 0, oldData.length); - src.duplicate().get(data, oldData.length, src.remaining()); - - _messageDataRef.setData(data); - } - - } - - @Override - public StoredMessage<T> allContentAdded() - { - return this; - } - - @Override - public int getContent(int offsetInMessage, ByteBuffer dst) - { - byte[] data = _messageDataRef.getData(); - if(data == null) - { - if(stored()) - { - checkMessageStoreOpen(); - data = AbstractBDBMessageStore.this.getAllContent(_messageId); - T metaData = _messageDataRef.getMetaData(); - if (metaData == null) - { - metaData = (T) getMessageMetaData(_messageId); - _messageDataRef = new MessageDataSoftRef<>(metaData, data); - } - else - { - _messageDataRef.setData(data); - } - } - else - { - data = new byte[0]; - } - } - - int length = Math.min(dst.remaining(), data.length - offsetInMessage); - dst.put(data, offsetInMessage, length); - return length; - } - - @Override - public ByteBuffer getContent(int offsetInMessage, int size) - { - byte[] data = _messageDataRef.getData(); - if(data == null) - { - if(stored()) - { - checkMessageStoreOpen(); - data = AbstractBDBMessageStore.this.getAllContent(_messageId); - T metaData = _messageDataRef.getMetaData(); - if (metaData == null) - { - metaData = (T) getMessageMetaData(_messageId); - _messageDataRef = new MessageDataSoftRef<>(metaData, data); - } - else - { - _messageDataRef.setData(data); - } - } - else - { - return null; - } - } - try - { - return ByteBuffer.wrap(data, offsetInMessage, Math.min(size, data.length - offsetInMessage)); - } - catch (IndexOutOfBoundsException e) - { - IndexOutOfBoundsException indexOutOfBoundsException = - new IndexOutOfBoundsException("Error wrapping data (data.length: " + data.length - + " offsetInMessage: " + offsetInMessage - + " size: " + size); - indexOutOfBoundsException.initCause(e); - throw indexOutOfBoundsException; - } - - } - - synchronized Runnable store(Transaction txn) - { - if (!stored()) - { - - AbstractBDBMessageStore.this.storeMetaData(txn, _messageId, _messageDataRef.getMetaData()); - AbstractBDBMessageStore.this.addContent(txn, _messageId, 0, - _messageDataRef.getData() == null - ? ByteBuffer.allocate(0) - : ByteBuffer.wrap(_messageDataRef.getData())); - - - MessageDataRef<T> hardRef = _messageDataRef; - MessageDataSoftRef<T> messageDataSoftRef; - MessageData<T> ref; - do - { - messageDataSoftRef = new MessageDataSoftRef<>(hardRef.getMetaData(), hardRef.getData()); - ref = messageDataSoftRef.get(); - } - while (ref == null); - - _messageDataRef = messageDataSoftRef; - - class Pointer implements Runnable - { - private MessageData<T> _ref; - - Pointer(final MessageData<T> ref) - { - _ref = ref; - } - - @Override - public void run() - { - _ref = null; - } - } - return new Pointer(ref); - } - else - { - return new Runnable() - { - - @Override - public void run() - { - } - }; - } - } - - synchronized FutureResult flushToStore() - { - if(!stored()) - { - checkMessageStoreOpen(); - - Transaction txn; - try - { - txn = getEnvironmentFacade().getEnvironment().beginTransaction( - null, null); - } - catch (RuntimeException e) - { - throw getEnvironmentFacade().handleDatabaseException("failed to begin transaction", e); - } - store(txn); - getEnvironmentFacade().commit(txn, true); - - storedSizeChangeOccurred(getMetaData().getContentSize()); - } - return FutureResult.IMMEDIATE_FUTURE; - } - - @Override - public void remove() - { - checkMessageStoreOpen(); - - int delta = getMetaData().getContentSize(); - removeMessage(_messageId, false); - storedSizeChangeOccurred(-delta); - } - - @Override - public boolean isInMemory() - { - return _messageDataRef.isHardRef(); - } - - private boolean stored() - { - return !_messageDataRef.isHardRef(); - } - - @Override - public boolean flowToDisk() - { - flushToStore(); - return true; - } - - @Override - public String toString() - { - return this.getClass() + "[messageId=" + _messageId + "]"; - } - } - - - private class BDBTransaction implements org.apache.qpid.server.store.Transaction - { - private Transaction _txn; - private int _storeSizeIncrease; - private final List<Runnable> _preCommitActions = new ArrayList<>(); - private final List<Runnable> _postCommitActions = new ArrayList<>(); - - private BDBTransaction() throws StoreException - { - try - { - _txn = getEnvironmentFacade().getEnvironment().beginTransaction(null, null); - } - catch(RuntimeException e) - { - throw getEnvironmentFacade().handleDatabaseException("Cannot create store transaction", e); - } - } - - @Override - public MessageEnqueueRecord enqueueMessage(TransactionLogResource queue, EnqueueableMessage message) throws StoreException - { - checkMessageStoreOpen(); - - if(message.getStoredMessage() instanceof StoredBDBMessage) - { - final StoredBDBMessage storedMessage = (StoredBDBMessage) message.getStoredMessage(); - final long contentSize = storedMessage.getMetaData().getContentSize(); - _preCommitActions.add(new Runnable() - { - @Override - public void run() - { - _postCommitActions.add(storedMessage.store(_txn)); - _storeSizeIncrease += contentSize; - } - }); - - } - - AbstractBDBMessageStore.this.enqueueMessage(_txn, queue, message.getMessageNumber()); - return new BDBEnqueueRecord(queue.getId(), message.getMessageNumber()); - } - - @Override - public void dequeueMessage(final MessageEnqueueRecord enqueueRecord) - { - checkMessageStoreOpen(); - - AbstractBDBMessageStore.this.dequeueMessage(_txn, enqueueRecord.getQueueId(), - enqueueRecord.getMessageNumber()); - } - - @Override - public void commitTran() throws StoreException - { - checkMessageStoreOpen(); - doPreCommitActions(); - AbstractBDBMessageStore.this.commitTranImpl(_txn, true); - doPostCommitActions(); - AbstractBDBMessageStore.this.storedSizeChangeOccurred(_storeSizeIncrease); - } - - private void doPreCommitActions() - { - for(Runnable action : _preCommitActions) - { - action.run(); - } - _preCommitActions.clear(); - } - - private void doPostCommitActions() - { - for(Runnable action : _postCommitActions) - { - action.run(); - } - _postCommitActions.clear(); - } - - @Override - public FutureResult commitTranAsync() throws StoreException - { - checkMessageStoreOpen(); - doPreCommitActions(); - AbstractBDBMessageStore.this.storedSizeChangeOccurred(_storeSizeIncrease); - FutureResult futureResult = AbstractBDBMessageStore.this.commitTranImpl(_txn, false); - doPostCommitActions(); - return futureResult; - } - - @Override - public void abortTran() throws StoreException - { - checkMessageStoreOpen(); - _preCommitActions.clear(); - _postCommitActions.clear(); - AbstractBDBMessageStore.this.abortTran(_txn); - } - - @Override - public void removeXid(final StoredXidRecord record) - { - checkMessageStoreOpen(); - - AbstractBDBMessageStore.this.removeXid(_txn, record.getFormat(), record.getGlobalId(), record.getBranchId()); - } - - @Override - public StoredXidRecord recordXid(final long format, final byte[] globalId, final byte[] branchId, final EnqueueRecord[] enqueues, - final DequeueRecord[] dequeues) throws StoreException - { - checkMessageStoreOpen(); - - _postCommitActions.addAll(AbstractBDBMessageStore.this.recordXid(_txn, format, globalId, branchId, enqueues, dequeues)); - return new BDBStoredXidRecord(format, globalId, branchId); - } - - } - - private static class BDBStoredXidRecord implements org.apache.qpid.server.store.Transaction.StoredXidRecord - { - private final long _format; - private final byte[] _globalId; - private final byte[] _branchId; - - public BDBStoredXidRecord(final long format, final byte[] globalId, final byte[] branchId) - { - _format = format; - _globalId = globalId; - _branchId = branchId; - } - - @Override - public long getFormat() - { - return _format; - } - - @Override - public byte[] getGlobalId() - { - return _globalId; - } - - @Override - public byte[] getBranchId() - { - return _branchId; - } - - @Override - public boolean equals(final Object o) - { - if (this == o) - { - return true; - } - if (o == null || getClass() != o.getClass()) - { - return false; - } - - final BDBStoredXidRecord that = (BDBStoredXidRecord) o; - - return _format == that._format - && Arrays.equals(_globalId, that._globalId) - && Arrays.equals(_branchId, that._branchId); - - } - - @Override - public int hashCode() - { - int result = (int) (_format ^ (_format >>> 32)); - result = 31 * result + Arrays.hashCode(_globalId); - result = 31 * result + Arrays.hashCode(_branchId); - return result; - } - } - public static class BDBEnqueueRecord implements MessageEnqueueRecord - { - private final UUID _queueId; - - private final long _messageNumber; - - public BDBEnqueueRecord(final UUID queueid, final long messageNumber) - { - _queueId = queueid; - _messageNumber = messageNumber; - } - - public long getMessageNumber() - { - return _messageNumber; - } - - public UUID getQueueId() - { - return _queueId; - } - - } - - private class BDBMessageStoreReader implements MessageStoreReader - { - @Override - public void visitMessages(final MessageHandler handler) throws StoreException - { - checkMessageStoreOpen(); - visitMessagesInternal(handler, getEnvironmentFacade()); - } - - @Override - public StoredMessage<?> getMessage(final long messageId) - { - checkMessageStoreOpen(); - return getMessageInternal(messageId, getEnvironmentFacade()); - } - - @Override - public void close() - { - - } - - @Override - public void visitMessageInstances(final TransactionLogResource queue, final MessageInstanceHandler handler) throws StoreException - { - checkMessageStoreOpen(); - - Cursor cursor = null; - List<QueueEntryKey> entries = new ArrayList<QueueEntryKey>(); - try - { - cursor = getDeliveryDb().openCursor(null, null); - DatabaseEntry key = new DatabaseEntry(); - DatabaseEntry value = new DatabaseEntry(); - - QueueEntryBinding keyBinding = QueueEntryBinding.getInstance(); - keyBinding.objectToEntry(new QueueEntryKey(queue.getId(),0l), key); - - if(cursor.getSearchKeyRange(key,value,LockMode.DEFAULT) == OperationStatus.SUCCESS) - { - QueueEntryKey entry = keyBinding.entryToObject(key); - if(entry.getQueueId().equals(queue.getId())) - { - entries.add(entry); - } - while (cursor.getNext(key, value, LockMode.DEFAULT) == OperationStatus.SUCCESS) - { - entry = keyBinding.entryToObject(key); - if(entry.getQueueId().equals(queue.getId())) - { - entries.add(entry); - } - else - { - break; - } - } - } - } - catch (RuntimeException e) - { - throw getEnvironmentFacade().handleDatabaseException("Cannot visit message instances", e); - } - finally - { - closeCursorSafely(cursor, getEnvironmentFacade()); - } - - for(QueueEntryKey entry : entries) - { - UUID queueId = entry.getQueueId(); - long messageId = entry.getMessageId(); - if (!handler.handle(new BDBEnqueueRecord(queueId, messageId))) - { - break; - } - } - - } - - - - @Override - public void visitMessageInstances(final MessageInstanceHandler handler) throws StoreException - { - checkMessageStoreOpen(); - - Cursor cursor = null; - List<QueueEntryKey> entries = new ArrayList<QueueEntryKey>(); - try - { - cursor = getDeliveryDb().openCursor(null, null); - DatabaseEntry key = new DatabaseEntry(); - QueueEntryBinding keyBinding = QueueEntryBinding.getInstance(); - - DatabaseEntry value = new DatabaseEntry(); - while (cursor.getNext(key, value, LockMode.DEFAULT) == OperationStatus.SUCCESS) - { - QueueEntryKey entry = keyBinding.entryToObject(key); - entries.add(entry); - } - } - catch (RuntimeException e) - { - throw getEnvironmentFacade().handleDatabaseException("Cannot visit message instances", e); - } - finally - { - closeCursorSafely(cursor, getEnvironmentFacade()); - } - - for(QueueEntryKey entry : entries) - { - UUID queueId = entry.getQueueId(); - long messageId = entry.getMessageId(); - if (!handler.handle(new BDBEnqueueRecord(queueId, messageId))) - { - break; - } - } - - } - - @Override - public void visitDistributedTransactions(final DistributedTransactionHandler handler) throws StoreException - { - checkMessageStoreOpen(); - - Cursor 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); - if (!handler.handle(new BDBStoredXidRecord(xid.getFormat(), xid.getGlobalId(), xid.getBranchId()), - preparedTransaction.getEnqueues(), preparedTransaction.getDequeues())) - { - break; - } - } - - } - catch (RuntimeException e) - { - throw getEnvironmentFacade().handleDatabaseException("Cannot recover distributed transactions", e); - } - finally - { - closeCursorSafely(cursor, getEnvironmentFacade()); - } - } - - - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBBackup.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBBackup.java deleted file mode 100644 index 045a4a05e6..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBBackup.java +++ /dev/null @@ -1,351 +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.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FilenameFilter; -import java.io.IOException; -import java.util.LinkedList; -import java.util.List; -import java.util.Properties; - -import com.sleepycat.je.DatabaseException; -import com.sleepycat.je.Environment; -import com.sleepycat.je.EnvironmentConfig; -import com.sleepycat.je.util.DbBackup; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.server.store.StoreException; -import org.apache.qpid.util.CommandLineParser; -import org.apache.qpid.util.FileUtils; - -/** - * BDBBackup is a utility for taking hot backups of the current state of a BDB transaction log database. - * <p> - * This utility makes the following assumptions/performs the following actions: - * <p> - * <ul> <li>The from and to directory locations will already exist. This scripts does not create them. <li>If this - * script fails to complete in one minute it will terminate. <li>This script always exits with code 1 on error, code 0 - * on success (standard unix convention). <li>This script will log out at info level, when it starts and ends and a list - * of all files backed up. <li>This script logs all errors at error level. <li>This script does not perform regular - * backups, wrap its calling script in a cron job or similar to do this. </ul> - * <p> - * This utility is build around the BDB provided backup helper utility class, DbBackup. This utility class provides - * an ability to force BDB to stop writing to the current log file set, whilst the backup is taken, to ensure that a - * consistent snapshot is acquired. Preventing BDB from writing to the current log file set, does not stop BDB from - * continuing to run concurrently while the backup is running, it simply moves onto a new set of log files; this - * provides a 'hot' backup facility. - * <p> - * DbBackup can also help with incremental backups, by providing the number of the last log file backed up. - * Subsequent backups can be taken, from later log files only. In a messaging application, messages are not expected to - * be long-lived in most cases, so the log files will usually have been completely turned over between backups. This - * utility does not support incremental backups for this reason. - * <p> - * If the database is locked by BDB, as is required when using transactions, and therefore will always be the case - * in Qpid, this utility cannot make use of the DbBackup utility in a seperate process. DbBackup, needs to ensure that - * the BDB envinronment used to take the backup has exclusive write access to the log files. This utility can take a - * backup as a standalone utility against log files, when a broker is not running, using the {@link #takeBackup(String, - *String,com.sleepycat.je.Environment)} method. - * <p> - * A seperate backup machanism is provided by the {@link #takeBackupNoLock(String,String)} method which can take a - * hot backup against a running broker. This works by finding out the set of files to copy, and then opening them all to - * read, and repeating this process until a consistent set of open files is obtained. This is done to avoid the - * situation where the BDB cleanup thread deletes a file, between the directory listing and opening of the file to copy. - * All consistently opened files are copied. This is the default mechanism the the {@link #main} method of this utility - * uses. - */ -public class BDBBackup -{ - /** Used for debugging. */ - private static final Logger log = LoggerFactory.getLogger(BDBBackup.class); - - /** Used for communicating with the user. */ - private static final Logger console = LoggerFactory.getLogger("Console"); - - /** Defines the suffix used to identify BDB log files. */ - private static final String LOG_FILE_SUFFIX = ".jdb"; - - /** Defines the command line format for this utility. */ - public static final String[][] COMMAND_LINE_SPEC = - new String[][] - { - { "fromdir", "The path to the directory to back the bdb log file from.", "dir", "true" }, - { "todir", "The path to the directory to save the backed up bdb log files to.", "dir", "true" } - }; - - /** Defines the timeout to terminate the backup operation on if it fails to complete. One minte. */ - public static final long TIMEOUT = 60000; - - /** - * Runs a backup of the BDB log files in a specified directory, copying the backed up files to another specified - * directory. - * <p> - * The following arguments must be specified: - * <table> - * <caption>Command Line</caption> <tr><th> Option <th> Comment <tr><td> -fromdir <td> The path to the - * directory to back the bdb log file from. <tr><td> -todir <td> The path to the directory to save the backed up - * bdb log files to. </table> - * - * @param args The command line arguments. - */ - public static void main(String[] args) - { - // Process the command line using standard handling (errors and usage followed by System.exit when it is wrong). - Properties options = - CommandLineParser.processCommandLine(args, new CommandLineParser(COMMAND_LINE_SPEC), System.getProperties()); - - // Extract the from and to directory locations and perform a backup between them. - try - { - String fromDir = options.getProperty("fromdir"); - String toDir = options.getProperty("todir"); - - log.info("BDBBackup Utility: Starting Hot Backup."); - - BDBBackup bdbBackup = new BDBBackup(); - String[] backedUpFiles = bdbBackup.takeBackupNoLock(fromDir, toDir); - - if (log.isInfoEnabled()) - { - log.info("BDBBackup Utility: Hot Backup Completed."); - log.info(backedUpFiles.length + " file(s) backed-up:"); - for(String backedUpFile : backedUpFiles) - { - log.info(backedUpFile); - } - } - } - catch (Exception e) - { - console.info("Backup script encountered an error and has failed: " + e.getMessage()); - log.error("Backup script got exception: " + e.getMessage(), e); - System.exit(1); - } - } - - /** - * Creates a backup of the BDB log files in the source directory, copying them to the destination directory. - * - * @param fromdir The source directory path. - * @param todir The destination directory path. - * @param environment An open BDB environment to perform the back up. - * - * @throws DatabaseException Any underlying execeptions from BDB are allowed to fall through. - */ - public void takeBackup(String fromdir, String todir, Environment environment) throws DatabaseException - { - DbBackup backupHelper = null; - - try - { - backupHelper = new DbBackup(environment); - - // Prevent BDB from writing to its log files while the backup it taken. - backupHelper.startBackup(); - - // Back up the BDB log files to the destination directory. - String[] filesForBackup = backupHelper.getLogFilesInBackupSet(); - - for (int i = 0; i < filesForBackup.length; i++) - { - File sourceFile = new File(fromdir + File.separator + filesForBackup[i]); - File destFile = new File(todir + File.separator + filesForBackup[i]); - FileUtils.copy(sourceFile, destFile); - } - } - finally - { - // Remember to exit backup mode, or all log files won't be cleaned and disk usage will bloat. - if (backupHelper != null) - { - backupHelper.endBackup(); - } - } - } - - /** - * Takes a hot backup when another process has locked the BDB database. - * - * @param fromdir The source directory path. - * @param todir The destination directory path. - * - * @return A list of all of the names of the files succesfully backed up. - */ - public String[] takeBackupNoLock(String fromdir, String todir) - { - if (log.isDebugEnabled()) - { - log.debug("public void takeBackupNoLock(String fromdir = " + fromdir + ", String todir = " + todir - + "): called"); - } - - File fromDirFile = new File(fromdir); - - if (!fromDirFile.isDirectory()) - { - throw new IllegalArgumentException("The specified fromdir(" + fromdir - + ") must be the directory containing your bdbstore."); - } - - File toDirFile = new File(todir); - - if (!toDirFile.exists()) - { - // Create directory if it doesn't exist - toDirFile.mkdirs(); - - if (log.isDebugEnabled()) - { - log.debug("Created backup directory:" + toDirFile); - } - } - - if (!toDirFile.isDirectory()) - { - throw new IllegalArgumentException("The specified todir(" + todir + ") must be a directory."); - } - - // Repeat until manage to open consistent set of files for reading. - boolean consistentSet = false; - FileInputStream[] fileInputStreams = new FileInputStream[0]; - File[] fileSet = new File[0]; - long start = System.currentTimeMillis(); - - while (!consistentSet) - { - // List all .jdb files in the directory. - fileSet = fromDirFile.listFiles(new FilenameFilter() - { - public boolean accept(File dir, String name) - { - return name.endsWith(LOG_FILE_SUFFIX); - } - }); - - // Open them all for reading. - fileInputStreams = new FileInputStream[fileSet.length]; - - if (fileSet.length == 0) - { - throw new StoreException("There are no BDB log files to backup in the " + fromdir + " directory."); - } - - for (int i = 0; i < fileSet.length; i++) - { - try - { - fileInputStreams[i] = new FileInputStream(fileSet[i]); - } - catch (FileNotFoundException e) - { - // Close any files opened for reading so far. - for (int j = 0; j < i; j++) - { - if (fileInputStreams[j] != null) - { - try - { - fileInputStreams[j].close(); - } - catch (IOException ioEx) - { - // Rethrow this as a runtime exception, as something strange has happened. - throw new StoreException(ioEx); - } - } - } - - // Could not open a consistent file set so try again. - break; - } - - // A consistent set has been opened if all files were sucesfully opened for reading. - if (i == (fileSet.length - 1)) - { - consistentSet = true; - } - } - - // Check that the script has not timed out, and raise an error if it has. - long now = System.currentTimeMillis(); - if ((now - start) > TIMEOUT) - { - throw new StoreException("Hot backup script failed to complete in " + (TIMEOUT / 1000) + " seconds."); - } - } - - // Copy the consistent set of open files. - List<String> backedUpFileNames = new LinkedList<String>(); - - for (int j = 0; j < fileSet.length; j++) - { - File destFile = new File(todir + File.separator + fileSet[j].getName()); - try - { - FileUtils.copy(fileSet[j], destFile); - } - catch (RuntimeException re) - { - Throwable cause = re.getCause(); - if ((cause != null) && (cause instanceof IOException)) - { - throw new StoreException(re.getMessage() + " fromDir:" + fromdir + " toDir:" + toDirFile, cause); - } - else - { - throw re; - } - } - - backedUpFileNames.add(destFile.getName()); - - // Close all of the files. - try - { - fileInputStreams[j].close(); - } - catch (IOException e) - { - // Rethrow this as a runtime exception, as something strange has happened. - throw new StoreException(e); - } - } - - return backedUpFileNames.toArray(new String[backedUpFileNames.size()]); - } - - /* - * Creates an environment for the bdb log files in the specified directory. This envrinonment can only be used - * to backup these files, if they are not locked by another database instance. - * - * @param fromdir The path to the directory to create the environment for. - * - * @throws DatabaseException Any underlying exceptions from BDB are allowed to fall through. - */ - private Environment createSourceDirEnvironment(String fromdir) throws DatabaseException - { - // Initialize the BDB backup utility on the source directory. - return new Environment(new File(fromdir), new EnvironmentConfig()); - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBConfigurationStore.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBConfigurationStore.java deleted file mode 100644 index 87bd606f83..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBConfigurationStore.java +++ /dev/null @@ -1,612 +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 static org.apache.qpid.server.store.berkeleydb.BDBUtils.DEFAULT_DATABASE_CONFIG; -import static org.apache.qpid.server.store.berkeleydb.BDBUtils.abortTransactionSafely; -import static org.apache.qpid.server.store.berkeleydb.BDBUtils.closeCursorSafely; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicBoolean; - -import com.sleepycat.je.Cursor; -import com.sleepycat.je.Database; -import com.sleepycat.je.DatabaseEntry; -import com.sleepycat.je.LockMode; -import com.sleepycat.je.OperationStatus; -import com.sleepycat.je.Transaction; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.store.ConfiguredObjectRecord; -import org.apache.qpid.server.store.DurableConfigurationStore; -import org.apache.qpid.server.store.FileBasedSettings; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.MessageStoreProvider; -import org.apache.qpid.server.store.SizeMonitoringSettings; -import org.apache.qpid.server.store.StoreException; -import org.apache.qpid.server.store.berkeleydb.entry.HierarchyKey; -import org.apache.qpid.server.store.berkeleydb.tuple.ConfiguredObjectBinding; -import org.apache.qpid.server.store.berkeleydb.tuple.HierarchyKeyBinding; -import org.apache.qpid.server.store.berkeleydb.tuple.UUIDTupleBinding; -import org.apache.qpid.server.store.berkeleydb.upgrade.Upgrader; -import org.apache.qpid.server.store.handler.ConfiguredObjectRecordHandler; -import org.apache.qpid.util.FileUtils; - -/** - * Implementation of a DurableConfigurationStore backed by BDB JE - * that also provides a MessageStore. - */ -public class BDBConfigurationStore implements MessageStoreProvider, DurableConfigurationStore -{ - private static final Logger LOGGER = LoggerFactory.getLogger(BDBConfigurationStore.class); - - public static final int VERSION = 8; - private static final String CONFIGURED_OBJECTS_DB_NAME = "CONFIGURED_OBJECTS"; - private static final String CONFIGURED_OBJECT_HIERARCHY_DB_NAME = "CONFIGURED_OBJECT_HIERARCHY"; - - private final AtomicBoolean _configurationStoreOpen = new AtomicBoolean(); - - private final EnvironmentFacadeFactory _environmentFacadeFactory; - - private final ProvidedBDBMessageStore _providedMessageStore = new ProvidedBDBMessageStore(); - - private EnvironmentFacade _environmentFacade; - - private ConfiguredObject<?> _parent; - private final Class<? extends ConfiguredObject> _rootClass; - private boolean _overwrite; - private ConfiguredObjectRecord[] _initialRecords; - - public BDBConfigurationStore(final Class<? extends ConfiguredObject> rootClass) - { - this(new StandardEnvironmentFacadeFactory(), rootClass); - } - - public BDBConfigurationStore(EnvironmentFacadeFactory environmentFacadeFactory, Class<? extends ConfiguredObject> rootClass) - { - _environmentFacadeFactory = environmentFacadeFactory; - _rootClass = rootClass; - } - - @Override - public void openConfigurationStore(ConfiguredObject<?> parent, - final boolean overwrite, - final ConfiguredObjectRecord... initialRecords) - { - if (_configurationStoreOpen.compareAndSet(false, true)) - { - _parent = parent; - - if (_environmentFacade == null) - { - _environmentFacade = _environmentFacadeFactory.createEnvironmentFacade(parent); - _overwrite = overwrite; - _initialRecords = initialRecords; - } - else - { - throw new IllegalStateException("The database have been already opened as message store"); - } - } - } - - private void clearConfigurationRecords() - { - checkConfigurationStoreOpen(); - - _environmentFacade.clearDatabase(CONFIGURED_OBJECTS_DB_NAME, DEFAULT_DATABASE_CONFIG); - _environmentFacade.clearDatabase(CONFIGURED_OBJECT_HIERARCHY_DB_NAME, DEFAULT_DATABASE_CONFIG); - } - - @Override - public void upgradeStoreStructure() throws StoreException - { - try - { - new Upgrader(_environmentFacade.getEnvironment(), _parent).upgradeIfNecessary(); - if(_overwrite) - { - clearConfigurationRecords(); - _overwrite = false; - } - if(getConfiguredObjectsDb().count() == 0l) - { - update(true, _initialRecords); - } - _initialRecords = new ConfiguredObjectRecord[0]; - } - catch (RuntimeException e) - { - throw _environmentFacade.handleDatabaseException("Cannot upgrade store", e); - } - } - @Override - public void visitConfiguredObjectRecords(ConfiguredObjectRecordHandler handler) - { - checkConfigurationStoreOpen(); - - try - { - handler.begin(); - doVisitAllConfiguredObjectRecords(handler); - handler.end(); - } - catch (RuntimeException e) - { - throw _environmentFacade.handleDatabaseException("Cannot visit configured object records", e); - } - } - - private void doVisitAllConfiguredObjectRecords(ConfiguredObjectRecordHandler handler) - { - Map<UUID, BDBConfiguredObjectRecord> configuredObjects = new HashMap<UUID, BDBConfiguredObjectRecord>(); - Cursor objectsCursor = null; - Cursor hierarchyCursor = null; - try - { - objectsCursor = getConfiguredObjectsDb().openCursor(null, null); - DatabaseEntry key = new DatabaseEntry(); - DatabaseEntry value = new DatabaseEntry(); - - - while (objectsCursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) - { - UUID id = UUIDTupleBinding.getInstance().entryToObject(key); - - BDBConfiguredObjectRecord configuredObject = - (BDBConfiguredObjectRecord) new ConfiguredObjectBinding(id).entryToObject(value); - configuredObjects.put(configuredObject.getId(), configuredObject); - } - - // set parents - hierarchyCursor = getConfiguredObjectHierarchyDb().openCursor(null, null); - while (hierarchyCursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) - { - HierarchyKey hk = HierarchyKeyBinding.getInstance().entryToObject(key); - UUID parentId = UUIDTupleBinding.getInstance().entryToObject(value); - BDBConfiguredObjectRecord child = configuredObjects.get(hk.getChildId()); - if(child != null) - { - ConfiguredObjectRecord parent = configuredObjects.get(parentId); - if(parent != null) - { - child.addParent(hk.getParentType(), parent); - } - } - } - } - finally - { - closeCursorSafely(objectsCursor, _environmentFacade); - closeCursorSafely(hierarchyCursor, _environmentFacade); - } - - for (ConfiguredObjectRecord record : configuredObjects.values()) - { - boolean shouldContinue = handler.handle(record); - if (!shouldContinue) - { - break; - } - } - - } - - public EnvironmentFacade getEnvironmentFacade() - { - return _environmentFacade; - } - - @Override - public void closeConfigurationStore() throws StoreException - { - if (_configurationStoreOpen.compareAndSet(true, false)) - { - if (!_providedMessageStore.isMessageStoreOpen()) - { - closeEnvironment(); - } - } - } - - private void closeEnvironment() - { - if (_environmentFacade != null) - { - try - { - _environmentFacade.close(); - _environmentFacade = null; - } - catch (RuntimeException e) - { - throw new StoreException("Exception occurred on message store close", e); - } - } - } - - @Override - public void create(ConfiguredObjectRecord configuredObject) throws StoreException - { - checkConfigurationStoreOpen(); - - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Create " + configuredObject); - } - - com.sleepycat.je.Transaction txn = null; - try - { - txn = _environmentFacade.getEnvironment().beginTransaction(null, null); - storeConfiguredObjectEntry(txn, configuredObject); - txn.commit(); - txn = null; - } - catch (RuntimeException e) - { - throw _environmentFacade.handleDatabaseException("Error creating configured object " + configuredObject - + " in database: " + e.getMessage(), e); - } - finally - { - if (txn != null) - { - abortTransactionSafely(txn, _environmentFacade); - } - } - } - - @Override - public UUID[] remove(final ConfiguredObjectRecord... objects) throws StoreException - { - checkConfigurationStoreOpen(); - - com.sleepycat.je.Transaction txn = null; - try - { - txn = _environmentFacade.getEnvironment().beginTransaction(null, null); - - Collection<UUID> removed = new ArrayList<UUID>(objects.length); - for(ConfiguredObjectRecord record : objects) - { - if(removeConfiguredObject(txn, record) == OperationStatus.SUCCESS) - { - removed.add(record.getId()); - } - } - - txn.commit(); - txn = null; - return removed.toArray(new UUID[removed.size()]); - } - catch (RuntimeException e) - { - throw _environmentFacade.handleDatabaseException("Error deleting configured objects from database", e); - } - finally - { - if (txn != null) - { - abortTransactionSafely(txn, _environmentFacade); - } - } - } - - @Override - public void update(boolean createIfNecessary, ConfiguredObjectRecord... records) throws StoreException - { - checkConfigurationStoreOpen(); - - com.sleepycat.je.Transaction txn = null; - try - { - txn = _environmentFacade.getEnvironment().beginTransaction(null, null); - for(ConfiguredObjectRecord record : records) - { - update(createIfNecessary, record, txn); - } - txn.commit(); - txn = null; - } - catch (RuntimeException e) - { - throw _environmentFacade.handleDatabaseException("Error updating configuration details within the store: " + e,e); - } - finally - { - if (txn != null) - { - abortTransactionSafely(txn, _environmentFacade); - } - } - } - - private void update(boolean createIfNecessary, ConfiguredObjectRecord record, com.sleepycat.je.Transaction txn) throws StoreException - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Updating, creating " + createIfNecessary + " : " + record); - } - - DatabaseEntry key = new DatabaseEntry(); - UUIDTupleBinding keyBinding = UUIDTupleBinding.getInstance(); - keyBinding.objectToEntry(record.getId(), key); - - DatabaseEntry value = new DatabaseEntry(); - DatabaseEntry newValue = new DatabaseEntry(); - ConfiguredObjectBinding configuredObjectBinding = ConfiguredObjectBinding.getInstance(); - - OperationStatus status = getConfiguredObjectsDb().get(txn, key, value, LockMode.DEFAULT); - final boolean isNewRecord = status == OperationStatus.NOTFOUND; - if (status == OperationStatus.SUCCESS || (createIfNecessary && isNewRecord)) - { - // write the updated entry to the store - configuredObjectBinding.objectToEntry(record, newValue); - status = getConfiguredObjectsDb().put(txn, key, newValue); - if (status != OperationStatus.SUCCESS) - { - throw new StoreException("Error updating configuration details within the store: " + status); - } - if(isNewRecord) - { - writeHierarchyRecords(txn, record); - } - } - else if (status != OperationStatus.NOTFOUND) - { - throw new StoreException("Error finding configuration details within the store: " + status); - } - } - - - private void storeConfiguredObjectEntry(final Transaction txn, ConfiguredObjectRecord configuredObject) throws StoreException - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Storing configured object record: " + configuredObject); - } - DatabaseEntry key = new DatabaseEntry(); - UUIDTupleBinding uuidBinding = UUIDTupleBinding.getInstance(); - uuidBinding.objectToEntry(configuredObject.getId(), key); - DatabaseEntry value = new DatabaseEntry(); - ConfiguredObjectBinding queueBinding = ConfiguredObjectBinding.getInstance(); - - queueBinding.objectToEntry(configuredObject, value); - try - { - OperationStatus status = getConfiguredObjectsDb().put(txn, key, value); - if (status != OperationStatus.SUCCESS) - { - throw new StoreException("Error writing configured object " + configuredObject + " to database: " - + status); - } - writeHierarchyRecords(txn, configuredObject); - } - catch (RuntimeException e) - { - throw _environmentFacade.handleDatabaseException("Error writing configured object " + configuredObject - + " to database: " + e.getMessage(), e); - } - } - - private void writeHierarchyRecords(final Transaction txn, final ConfiguredObjectRecord configuredObject) - { - OperationStatus status; - HierarchyKeyBinding hierarchyBinding = HierarchyKeyBinding.getInstance(); - DatabaseEntry hierarchyKey = new DatabaseEntry(); - DatabaseEntry hierarchyValue = new DatabaseEntry(); - - for(Map.Entry<String, UUID> parent : configuredObject.getParents().entrySet()) - { - - hierarchyBinding.objectToEntry(new HierarchyKey(configuredObject.getId(), parent.getKey()), hierarchyKey); - UUIDTupleBinding.getInstance().objectToEntry(parent.getValue(), hierarchyValue); - status = getConfiguredObjectHierarchyDb().put(txn, hierarchyKey, hierarchyValue); - if (status != OperationStatus.SUCCESS) - { - throw new StoreException("Error writing configured object " + configuredObject + " parent record to database: " - + status); - } - } - } - - private OperationStatus removeConfiguredObject(Transaction tx, ConfiguredObjectRecord record) throws StoreException - { - UUID id = record.getId(); - Map<String, UUID> parents = record.getParents(); - - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Removing configured object: " + id); - } - DatabaseEntry key = new DatabaseEntry(); - - UUIDTupleBinding uuidBinding = UUIDTupleBinding.getInstance(); - uuidBinding.objectToEntry(id, key); - OperationStatus status = getConfiguredObjectsDb().delete(tx, key); - if(status == OperationStatus.SUCCESS) - { - for(String parentType : parents.keySet()) - { - DatabaseEntry hierarchyKey = new DatabaseEntry(); - HierarchyKeyBinding keyBinding = HierarchyKeyBinding.getInstance(); - keyBinding.objectToEntry(new HierarchyKey(record.getId(), parentType), hierarchyKey); - getConfiguredObjectHierarchyDb().delete(tx, hierarchyKey); - } - } - return status; - } - - @Override - public MessageStore getMessageStore() - { - return _providedMessageStore; - } - - private void checkConfigurationStoreOpen() - { - if (!isConfigurationStoreOpen()) - { - throw new IllegalStateException("Configuration store is not open"); - } - } - - @Override - public void onDelete(ConfiguredObject<?> parent) - { - FileBasedSettings fileBasedSettings = (FileBasedSettings)parent; - String storePath = fileBasedSettings.getStorePath(); - - if (storePath != null) - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Deleting store " + storePath); - } - - File configFile = new File(storePath); - if (!FileUtils.delete(configFile, true)) - { - LOGGER.info("Failed to delete the store at location " + storePath); - } - } - } - - private boolean isConfigurationStoreOpen() - { - return _configurationStoreOpen.get(); - } - - private Database getConfiguredObjectsDb() - { - return _environmentFacade.openDatabase(CONFIGURED_OBJECTS_DB_NAME, DEFAULT_DATABASE_CONFIG); - } - - private Database getConfiguredObjectHierarchyDb() - { - return _environmentFacade.openDatabase(CONFIGURED_OBJECT_HIERARCHY_DB_NAME, DEFAULT_DATABASE_CONFIG); - } - - class ProvidedBDBMessageStore extends AbstractBDBMessageStore - { - private final AtomicBoolean _messageStoreOpen = new AtomicBoolean(); - - private long _persistentSizeLowThreshold; - private long _persistentSizeHighThreshold; - - private ConfiguredObject<?> _parent; - - @Override - public void openMessageStore(final ConfiguredObject<?> parent) - { - if (_messageStoreOpen.compareAndSet(false, true)) - { - _parent = parent; - - final SizeMonitoringSettings sizeMonitorSettings = (SizeMonitoringSettings) parent; - _persistentSizeHighThreshold = sizeMonitorSettings.getStoreOverfullSize(); - _persistentSizeLowThreshold = sizeMonitorSettings.getStoreUnderfullSize(); - - if (_persistentSizeLowThreshold > _persistentSizeHighThreshold || _persistentSizeLowThreshold < 0l) - { - _persistentSizeLowThreshold = _persistentSizeHighThreshold; - } - } - } - - public boolean isMessageStoreOpen() - { - return _messageStoreOpen.get(); - } - - @Override - public void closeMessageStore() - { - _messageStoreOpen.set(false); - } - - @Override - public EnvironmentFacade getEnvironmentFacade() - { - return _environmentFacade; - } - - @Override - public void onDelete(ConfiguredObject<?> parent) - { - // Nothing to do, message store will be deleted when configuration store is deleted - } - - @Override - public String getStoreLocation() - { - return ((FileBasedSettings)(BDBConfigurationStore.this._parent)).getStorePath(); - } - - @Override - public File getStoreLocationAsFile() - { - return new File(getStoreLocation()); - } - - @Override - protected long getPersistentSizeLowThreshold() - { - return _persistentSizeLowThreshold; - } - - @Override - protected long getPersistentSizeHighThreshold() - { - return _persistentSizeHighThreshold; - } - - @Override - protected ConfiguredObject<?> getParent() - { - return _parent; - } - - @Override - protected void checkMessageStoreOpen() - { - if (!_messageStoreOpen.get()) - { - throw new IllegalStateException("Message store is not open"); - } - } - - @Override - protected Logger getLogger() - { - return LOGGER; - } - } - -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBConfiguredObjectRecord.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBConfiguredObjectRecord.java deleted file mode 100644 index 6db6217769..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBConfiguredObjectRecord.java +++ /dev/null @@ -1,114 +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.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import org.apache.qpid.server.store.ConfiguredObjectRecord; - -public class BDBConfiguredObjectRecord implements ConfiguredObjectRecord -{ - private final UUID _id; - private final String _type; - private final Map<String,Object> _attributes; - private Map<String, UUID> _parents = new HashMap<>(); - - public BDBConfiguredObjectRecord(final UUID id, final String type, final Map<String, Object> attributes) - { - _id = id; - _type = type; - _attributes = Collections.unmodifiableMap(attributes); - } - - public UUID getId() - { - return _id; - } - - public String getType() - { - return _type; - } - - public Map<String, Object> getAttributes() - { - return _attributes; - } - - void addParent(String parentType, ConfiguredObjectRecord parent) - { - _parents.put(parentType, parent.getId()); - } - - @Override - public Map<String, UUID> getParents() - { - return Collections.unmodifiableMap(_parents); - } - - @Override - public boolean equals(final Object o) - { - if (this == o) - { - return true; - } - if (o == null || getClass() != o.getClass()) - { - return false; - } - - final BDBConfiguredObjectRecord that = (BDBConfiguredObjectRecord) o; - - if (_attributes != null ? !_attributes.equals(that._attributes) : that._attributes != null) - { - return false; - } - if (_id != null ? !_id.equals(that._id) : that._id != null) - { - return false; - } - if (_type != null ? !_type.equals(that._type) : that._type != null) - { - return false; - } - - return true; - } - - @Override - public int hashCode() - { - int result = _id != null ? _id.hashCode() : 0; - result = 31 * result + (_type != null ? _type.hashCode() : 0); - return result; - } - - @Override - public String toString() - { - return "BDBConfiguredObjectRecord [id=" + _id + ", type=" + _type + ", name=" + (_attributes == null ? null : _attributes.get("name")) + ", parents=" + _parents + "]"; - } - -} 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 deleted file mode 100644 index 36c235d5a8..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java +++ /dev/null @@ -1,175 +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.util.concurrent.atomic.AtomicBoolean; - -import com.sleepycat.je.DatabaseException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.store.FileBasedSettings; -import org.apache.qpid.server.store.SizeMonitoringSettings; -import org.apache.qpid.server.store.StoreException; -import org.apache.qpid.util.FileUtils; - -/** - * Implementation of a MessageStore backed by BDB JE. - */ -public class BDBMessageStore extends AbstractBDBMessageStore -{ - private static final Logger LOGGER = LoggerFactory.getLogger(BDBMessageStore.class); - - private final EnvironmentFacadeFactory _environmentFacadeFactory; - - private final AtomicBoolean _messageStoreOpen = new AtomicBoolean(); - - private EnvironmentFacade _environmentFacade; - - private ConfiguredObject<?> _parent; - - private long _persistentSizeLowThreshold; - private long _persistentSizeHighThreshold; - - public BDBMessageStore() - { - this(new StandardEnvironmentFacadeFactory()); - } - - public BDBMessageStore(EnvironmentFacadeFactory environmentFacadeFactory) - { - _environmentFacadeFactory = environmentFacadeFactory; - } - - @Override - public void openMessageStore(final ConfiguredObject<?> parent) - { - if (_messageStoreOpen.compareAndSet(false, true)) - { - _parent = parent; - - final SizeMonitoringSettings sizeMonitorSettings = (SizeMonitoringSettings) parent; - _persistentSizeHighThreshold = sizeMonitorSettings.getStoreOverfullSize(); - _persistentSizeLowThreshold = sizeMonitorSettings.getStoreUnderfullSize(); - - if (_persistentSizeLowThreshold > _persistentSizeHighThreshold || _persistentSizeLowThreshold < 0l) - { - _persistentSizeLowThreshold = _persistentSizeHighThreshold; - } - - _environmentFacade = _environmentFacadeFactory.createEnvironmentFacade(parent); - } - } - - @Override - public void closeMessageStore() - { - if (_messageStoreOpen.compareAndSet(true, false)) - { - if (_environmentFacade != null) - { - try - { - _environmentFacade.close(); - _environmentFacade = null; - } - catch (DatabaseException e) - { - throw new StoreException("Exception occurred on message store close", e); - } - } - } - } - - @Override - public void onDelete(ConfiguredObject<?> parent) - { - FileBasedSettings fileBasedSettings = (FileBasedSettings)parent; - String storePath = fileBasedSettings.getStorePath(); - - if (storePath != null) - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Deleting store " + storePath); - } - - File configFile = new File(storePath); - if (!FileUtils.delete(configFile, true)) - { - LOGGER.info("Failed to delete the store at location " + storePath); - } - } - } - - @Override - public EnvironmentFacade getEnvironmentFacade() - { - return _environmentFacade; - } - - @Override - protected long getPersistentSizeLowThreshold() - { - return _persistentSizeLowThreshold; - } - - @Override - protected long getPersistentSizeHighThreshold() - { - return _persistentSizeHighThreshold; - } - - @Override - protected Logger getLogger() - { - return LOGGER; - } - - @Override - protected void checkMessageStoreOpen() - { - if (!_messageStoreOpen.get()) - { - throw new IllegalStateException("Message store is not open"); - } - } - - @Override - protected ConfiguredObject<?> getParent() - { - return _parent; - } - - @Override - public String getStoreLocation() - { - return ((FileBasedSettings)_parent).getStorePath(); - } - - @Override - public File getStoreLocationAsFile() - { - return new File(getStoreLocation()); - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfig.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfig.java deleted file mode 100644 index 9fc0b14af8..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfig.java +++ /dev/null @@ -1,39 +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.qpid.server.model.ManagedAttribute; -import org.apache.qpid.server.model.SystemConfig; -import org.apache.qpid.server.store.FileBasedSettings; -import org.apache.qpid.server.store.SizeMonitoringSettings; - -public interface BDBSystemConfig<X extends BDBSystemConfig<X>> extends SystemConfig<X>, FileBasedSettings, - SizeMonitoringSettings -{ - @ManagedAttribute(mandatory = true) - String getStorePath(); - - @ManagedAttribute(mandatory = true, defaultValue = "0") - Long getStoreUnderfullSize(); - - @ManagedAttribute(mandatory = true, defaultValue = "0") - Long getStoreOverfullSize(); -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfigImpl.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfigImpl.java deleted file mode 100644 index 90bb4b74ee..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfigImpl.java +++ /dev/null @@ -1,82 +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.util.Map; - -import org.apache.qpid.server.configuration.updater.TaskExecutor; -import org.apache.qpid.server.logging.EventLogger; -import org.apache.qpid.server.logging.LogRecorder; -import org.apache.qpid.server.model.AbstractSystemConfig; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.BrokerShutdownProvider; -import org.apache.qpid.server.model.ManagedAttributeField; -import org.apache.qpid.server.model.ManagedObject; -import org.apache.qpid.server.model.SystemConfigFactoryConstructor; -import org.apache.qpid.server.store.DurableConfigurationStore; - -@ManagedObject(category = false, type = BDBSystemConfigImpl.SYSTEM_CONFIG_TYPE) -public class BDBSystemConfigImpl extends AbstractSystemConfig<BDBSystemConfigImpl> implements BDBSystemConfig<BDBSystemConfigImpl> -{ - public static final String SYSTEM_CONFIG_TYPE = "BDB"; - - @ManagedAttributeField - private String _storePath; - @ManagedAttributeField - private Long _storeUnderfullSize; - @ManagedAttributeField - private Long _storeOverfullSize; - - - @SystemConfigFactoryConstructor - public BDBSystemConfigImpl(final TaskExecutor taskExecutor, - final EventLogger eventLogger, - final LogRecorder logRecorder, - final Map<String,Object> attributes, - final BrokerShutdownProvider brokerShutdownProvider) - { - super(taskExecutor, eventLogger, logRecorder, attributes, brokerShutdownProvider); - } - - @Override - protected DurableConfigurationStore createStoreObject() - { - return new BDBConfigurationStore(Broker.class); - } - - @Override - public String getStorePath() - { - return _storePath; - } - - @Override - public Long getStoreUnderfullSize() - { - return _storeUnderfullSize; - } - - @Override - public Long getStoreOverfullSize() - { - return _storeOverfullSize; - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBUtils.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBUtils.java deleted file mode 100644 index 1f730e6d03..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBUtils.java +++ /dev/null @@ -1,112 +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.je.CheckpointConfig; -import com.sleepycat.je.Cursor; -import com.sleepycat.je.DatabaseConfig; -import com.sleepycat.je.Environment; -import com.sleepycat.je.EnvironmentConfig; -import com.sleepycat.je.Transaction; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.server.store.StoreException; - -public class BDBUtils -{ - private static final Logger LOGGER = LoggerFactory.getLogger(BDBUtils.class); - - public static final DatabaseConfig DEFAULT_DATABASE_CONFIG = new DatabaseConfig().setTransactional(true).setAllowCreate(true); - - public static void closeCursorSafely(Cursor cursor, final EnvironmentFacade environmentFacade) throws StoreException - { - if (cursor != null) - { - try - { - cursor.close(); - } - catch (RuntimeException e) - { - // We need the possible side effect of the facade restarting the environment but don't care about the exception - throw environmentFacade.handleDatabaseException("Cannot close cursor", e); - } - } - } - - public static void abortTransactionSafely(Transaction tx, EnvironmentFacade environmentFacade) - { - try - { - if (tx != null) - { - tx.abort(); - } - } - catch (RuntimeException e) - { - // We need the possible side effect of the facade restarting the environment but don't care about the exception - environmentFacade.handleDatabaseException("Cannot abort transaction", e); - } - } - - public synchronized static void runCleaner(final Environment environment) - { - boolean cleanerWasRunning = Boolean.parseBoolean(environment.getConfig().getConfigParam(EnvironmentConfig.ENV_RUN_CLEANER)); - - try - { - if (cleanerWasRunning) - { - environment.getConfig().setConfigParam(EnvironmentConfig.ENV_RUN_CLEANER, Boolean.FALSE.toString()); - } - - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Cleaning logs"); - } - - boolean cleaned = false; - while (environment.cleanLog() > 0) - { - cleaned = true; - } - if (cleaned) - { - LOGGER.debug("Cleaned log"); - - CheckpointConfig force = new CheckpointConfig(); - force.setForce(true); - environment.checkpoint(force); - - LOGGER.debug("Checkpoint force complete"); - } - } - finally - { - if (cleanerWasRunning) - { - environment.getConfig().setConfigParam(EnvironmentConfig.ENV_RUN_CLEANER, Boolean.TRUE.toString()); - } - } - - } -} 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 deleted file mode 100644 index 6699de5dec..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CoalescingCommiter.java +++ /dev/null @@ -1,379 +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.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicBoolean; - -import com.sleepycat.je.DatabaseException; -import com.sleepycat.je.Environment; -import com.sleepycat.je.Transaction; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.server.util.FutureResult; - -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(); - if (Thread.currentThread() != _commitThread) - { - try - { - _commitThread.join(); - } - catch (InterruptedException ie) - { - Thread.currentThread().interrupt(); - throw new RuntimeException("Commit thread has not shutdown", ie); - } - } - } - - @Override - public FutureResult commit(Transaction tx, boolean syncCommit) - { - BDBCommitFutureResult commitFuture = new BDBCommitFutureResult(_commitThread, tx, syncCommit); - commitFuture.commit(); - return commitFuture; - } - - private static final class BDBCommitFutureResult implements FutureResult - { - private static final Logger LOGGER = LoggerFactory.getLogger(BDBCommitFutureResult.class); - - private final CommitThread _commitThread; - private final Transaction _tx; - private final boolean _syncCommit; - private RuntimeException _databaseException; - private boolean _complete; - - public BDBCommitFutureResult(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); - } - } - - public synchronized void waitForCompletion(long timeout) throws TimeoutException - { - long startTime= System.currentTimeMillis(); - long remaining = timeout; - - while (!isComplete() && remaining > 0) - { - _commitThread.explicitNotify(); - try - { - wait(remaining); - } - catch (InterruptedException e) - { - throw new RuntimeException(e); - } - if(!isComplete()) - { - remaining = (startTime + timeout) - System.currentTimeMillis(); - } - } - - if(remaining < 0l) - { - throw new TimeoutException("commit did not occur within given timeout period: " + timeout); - } - - 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 org.apache.qpid.server.store.berkeleydb.CoalescingCommiter.BDBCommitFutureResult} 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 org.apache.qpid.server.store.berkeleydb.CoalescingCommiter.BDBCommitFutureResult#complete()} and {@link org.apache.qpid.server.store.berkeleydb.CoalescingCommiter.BDBCommitFutureResult#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 = LoggerFactory.getLogger(CommitThread.class); - - private final AtomicBoolean _stopped = new AtomicBoolean(false); - private final Queue<BDBCommitFutureResult> _jobQueue = new ConcurrentLinkedQueue<BDBCommitFutureResult>(); - 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++) - { - BDBCommitFutureResult commit = _jobQueue.poll(); - if (commit == null) - { - break; - } - commit.complete(); - } - - } - catch (DatabaseException e) - { - try - { - LOGGER.error("Exception during environment log flush", e); - - for(int i = 0; i < size; i++) - { - BDBCommitFutureResult commit = _jobQueue.poll(); - if (commit == null) - { - break; - } - 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(BDBCommitFutureResult 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); - Environment environment = _environmentFacade.getEnvironment(); - BDBCommitFutureResult commit; - if (environment != null && environment.isValid()) - { - environment.flushLog(true); - while ((commit = _jobQueue.poll()) != null) - { - commit.complete(); - } - } - else - { - int abortedCommits = 0; - while ((commit = _jobQueue.poll()) != null) - { - abortedCommits++; - commit.abort(e); - } - if (LOGGER.isDebugEnabled() && abortedCommits > 0) - { - LOGGER.debug(abortedCommits + " commit(s) were aborted during close."); - } - } - - _lock.notifyAll(); - } - } - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CommitThreadWrapper.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CommitThreadWrapper.java deleted file mode 100644 index cbfeb2d9ff..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CommitThreadWrapper.java +++ /dev/null @@ -1,330 +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.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicBoolean; - -import com.sleepycat.je.CheckpointConfig; -import com.sleepycat.je.DatabaseException; -import com.sleepycat.je.Environment; -import com.sleepycat.je.Transaction; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.server.store.StoreException; -import org.apache.qpid.server.util.FutureResult; - -public class CommitThreadWrapper -{ - private final CommitThread _commitThread; - - public CommitThreadWrapper(String name, Environment env) - { - _commitThread = new CommitThread(name, env); - } - - public void startCommitThread() - { - _commitThread.start(); - } - - public void stopCommitThread() throws InterruptedException - { - _commitThread.close(); - _commitThread.join(); - } - - public FutureResult commit(Transaction tx, boolean syncCommit) - { - BDBCommitFutureResult commitFuture = new BDBCommitFutureResult(_commitThread, tx, syncCommit); - commitFuture.commit(); - return commitFuture; - } - - private static final class BDBCommitFutureResult implements FutureResult - { - private static final Logger LOGGER = LoggerFactory.getLogger(BDBCommitFutureResult.class); - - private final CommitThread _commitThread; - private final Transaction _tx; - private DatabaseException _databaseException; - private boolean _complete; - private boolean _syncCommit; - - public BDBCommitFutureResult(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(DatabaseException 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 StoreException(e); - } - } - - if(LOGGER.isDebugEnabled()) - { - long duration = System.currentTimeMillis() - startTime; - LOGGER.debug("waitForCompletion returning after " + duration + " ms for transaction " + _tx); - } - } - - @Override - public void waitForCompletion(final long timeout) throws TimeoutException - { - long startTime = System.currentTimeMillis(); - long remaining = timeout; - - while (!isComplete() && remaining > 0) - { - _commitThread.explicitNotify(); - try - { - wait(remaining); - } - catch (InterruptedException e) - { - throw new StoreException(e); - } - if(!isComplete()) - { - remaining = (startTime + timeout) - System.currentTimeMillis(); - } - } - - if(remaining < 0) - { - throw new TimeoutException("Commit did not complete within required timeout: " + timeout); - } - - 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 org.apache.qpid.server.store.berkeleydb.CommitThreadWrapper.BDBCommitFutureResult} 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 org.apache.qpid.server.store.berkeleydb.CommitThreadWrapper.BDBCommitFutureResult#complete()} and {@link org.apache.qpid.server.store.berkeleydb.CommitThreadWrapper.BDBCommitFutureResult#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 = LoggerFactory.getLogger(CommitThread.class); - - private final AtomicBoolean _stopped = new AtomicBoolean(false); - private final Queue<BDBCommitFutureResult> _jobQueue = new ConcurrentLinkedQueue<BDBCommitFutureResult>(); - private final CheckpointConfig _config = new CheckpointConfig(); - private final Object _lock = new Object(); - private Environment _environment; - - public CommitThread(String name, Environment env) - { - super(name); - _config.setForce(true); - _environment = env; - } - - public void explicitNotify() - { - synchronized (_lock) - { - _lock.notify(); - } - } - - public void run() - { - while (!_stopped.get()) - { - synchronized (_lock) - { - while (!_stopped.get() && !hasJobs()) - { - try - { - // RHM-7 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.flushLog(true); - - if(LOGGER.isDebugEnabled()) - { - long duration = System.currentTimeMillis() - startTime; - LOGGER.debug("flushLog completed in " + duration + " ms"); - } - - for(int i = 0; i < size; i++) - { - BDBCommitFutureResult commit = _jobQueue.poll(); - commit.complete(); - } - - } - catch (DatabaseException e) - { - try - { - LOGGER.error("Exception during environment log flush", e); - - for(int i = 0; i < size; i++) - { - BDBCommitFutureResult commit = _jobQueue.poll(); - commit.abort(e); - } - } - finally - { - LOGGER.error("Closing store environment", e); - - try - { - _environment.close(); - } - catch (DatabaseException ex) - { - LOGGER.error("Exception closing store environment", ex); - } - } - } - } - - private boolean hasJobs() - { - return !_jobQueue.isEmpty(); - } - - public void addJob(BDBCommitFutureResult commit, final boolean sync) - { - - _jobQueue.add(commit); - if(sync) - { - synchronized (_lock) - { - _lock.notifyAll(); - } - } - } - - public void close() - { - synchronized (_lock) - { - _stopped.set(true); - _lock.notifyAll(); - } - } - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/Committer.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/Committer.java deleted file mode 100644 index 9bd1aaf3e0..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/Committer.java +++ /dev/null @@ -1,34 +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.je.Transaction; - -import org.apache.qpid.server.util.FutureResult; - -public interface Committer -{ - void start(); - - FutureResult commit(Transaction tx, boolean syncCommit); - - void stop(); -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvHomeRegistry.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvHomeRegistry.java deleted file mode 100644 index ad592ef1f6..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvHomeRegistry.java +++ /dev/null @@ -1,88 +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.io.IOException; -import java.util.HashSet; -import java.util.Set; - -import org.apache.qpid.server.store.StoreException; - -/** - * JE permits the same environment to opened for write many times from within the same JVM. - * The Java Broker needs to disallow this as the stores of many VHNs or many VH - */ -public class EnvHomeRegistry -{ - private static final EnvHomeRegistry _instance = new EnvHomeRegistry(); - private final Set<String> _canonicalNames = new HashSet<>(); - - public static final EnvHomeRegistry getInstance() - { - return _instance; - } - - // default for unit testing - EnvHomeRegistry() - { - super(); - } - - public synchronized void registerHome(final File home) throws StoreException - { - if (home == null) - { - throw new IllegalArgumentException("home parameter cannot be null"); - } - - String canonicalForm = getCanonicalForm(home); - if (_canonicalNames.contains(canonicalForm)) - { - throw new IllegalArgumentException("JE Home " + home + " is already in use"); - } - _canonicalNames.add(canonicalForm); - } - - - public synchronized void deregisterHome(final File home) throws StoreException - { - if (home == null) - { - throw new IllegalArgumentException("home parameter cannot be null"); - } - - String canonicalForm = getCanonicalForm(home); - _canonicalNames.remove(canonicalForm); - } - - private String getCanonicalForm(final File home) - { - try - { - return home.getCanonicalPath(); - } - catch (IOException e) - { - throw new StoreException("Failed to resolve " + home + " into canonical form", e); - } - } - -} 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 deleted file mode 100644 index e3969c467c..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvironmentFacade.java +++ /dev/null @@ -1,66 +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.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import com.sleepycat.je.Database; -import com.sleepycat.je.DatabaseConfig; -import com.sleepycat.je.DatabaseEntry; -import com.sleepycat.je.Environment; -import com.sleepycat.je.EnvironmentConfig; -import com.sleepycat.je.Sequence; -import com.sleepycat.je.SequenceConfig; -import com.sleepycat.je.Transaction; - -import org.apache.qpid.server.util.FutureResult; - -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(); - - Database openDatabase(String databaseName, DatabaseConfig databaseConfig); - Database clearDatabase(String databaseName, DatabaseConfig databaseConfig); - - Sequence openSequence(Database database, DatabaseEntry sequenceKey, SequenceConfig sequenceConfig); - - Transaction beginTransaction(); - - FutureResult commit(com.sleepycat.je.Transaction tx, boolean sync); - - RuntimeException handleDatabaseException(String contextMessage, RuntimeException e); - - String getStoreLocation(); - - void closeDatabase(String name); - void close(); - -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvironmentFacadeFactory.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvironmentFacadeFactory.java deleted file mode 100644 index 39f8827754..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvironmentFacadeFactory.java +++ /dev/null @@ -1,31 +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.util.Map; - -import org.apache.qpid.server.model.ConfiguredObject; - -public interface EnvironmentFacadeFactory -{ - EnvironmentFacade createEnvironmentFacade(final ConfiguredObject<?> parent); - -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/FieldTableEncoding.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/FieldTableEncoding.java deleted file mode 100644 index e3cbeccd6e..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/FieldTableEncoding.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.berkeleydb; - -import com.sleepycat.bind.tuple.TupleInput; -import com.sleepycat.bind.tuple.TupleOutput; -import com.sleepycat.je.DatabaseException; - -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.store.StoreException; - -import java.io.ByteArrayInputStream; -import java.io.DataInputStream; -import java.io.IOException; - -public class FieldTableEncoding -{ - private FieldTableEncoding() - { - } - - public static FieldTable readFieldTable(TupleInput tupleInput) throws DatabaseException - { - long length = tupleInput.readLong(); - if (length <= 0) - { - return null; - } - else - { - - byte[] data = new byte[(int)length]; - tupleInput.readFast(data); - - try - { - return new FieldTable(new DataInputStream(new ByteArrayInputStream(data)),length); - } - catch (IOException e) - { - throw new StoreException(e); - } - - } - - } - - public static void writeFieldTable(FieldTable fieldTable, TupleOutput tupleOutput) - { - - if (fieldTable == null) - { - tupleOutput.writeLong(0); - } - else - { - tupleOutput.writeLong(fieldTable.getEncodedSize()); - tupleOutput.writeFast(fieldTable.getDataAsBytes()); - } - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/HASettings.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/HASettings.java deleted file mode 100644 index fd4a7bc1c7..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/HASettings.java +++ /dev/null @@ -1,39 +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.qpid.server.store.FileBasedSettings; - -public interface HASettings extends FileBasedSettings -{ - String getGroupName(); - - String getAddress(); - - String getHelperAddress(); - - boolean isDesignatedPrimary(); - - int getPriority(); - - int getQuorumOverride(); - - String getHelperNodeName(); -} 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 deleted file mode 100644 index a499f10ce1..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/LoggingAsyncExceptionListener.java +++ /dev/null @@ -1,38 +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.je.ExceptionEvent; -import com.sleepycat.je.ExceptionListener; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class LoggingAsyncExceptionListener implements ExceptionListener -{ - private static final Logger LOGGER = LoggerFactory.getLogger(LoggingAsyncExceptionListener.class); - - @Override - public void exceptionThrown(ExceptionEvent event) - { - LOGGER.error("Asynchronous exception thrown by BDB thread '" + event.getThreadName() + "'", event.getException()); - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentConfiguration.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentConfiguration.java deleted file mode 100644 index 02ee53a53a..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentConfiguration.java +++ /dev/null @@ -1,29 +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.util.Map; - -public interface StandardEnvironmentConfiguration -{ - String getName(); - String getStorePath(); - Map<String, String> getParameters(); -} 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 deleted file mode 100644 index 3c65da63d5..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacade.java +++ /dev/null @@ -1,368 +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.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -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.Sequence; -import com.sleepycat.je.SequenceConfig; -import com.sleepycat.je.Transaction; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.server.store.StoreException; -import org.apache.qpid.server.util.FutureResult; -import org.apache.qpid.server.store.berkeleydb.logging.Log4jLoggingHandler; - -public class StandardEnvironmentFacade implements EnvironmentFacade -{ - private static final Logger LOGGER = LoggerFactory.getLogger(StandardEnvironmentFacade.class); - - private final String _storePath; - private final ConcurrentMap<String, Database> _cachedDatabases = new ConcurrentHashMap<>(); - private final ConcurrentMap<DatabaseEntry, Sequence> _cachedSequences = new ConcurrentHashMap<>(); - - private Environment _environment; - private final Committer _committer; - private final File _environmentPath; - - public StandardEnvironmentFacade(StandardEnvironmentConfiguration configuration) - { - _storePath = configuration.getStorePath(); - - if (LOGGER.isInfoEnabled()) - { - LOGGER.info("Creating environment at environment path " + _storePath); - } - - _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."); - } - } - - String name = configuration.getName(); - EnvironmentConfig envConfig = new EnvironmentConfig(); - envConfig.setAllowCreate(true); - envConfig.setTransactional(true); - - envConfig.setConfigParam(EnvironmentConfig.FILE_LOGGING_LEVEL, "OFF"); - envConfig.setConfigParam(EnvironmentConfig.CONSOLE_LOGGING_LEVEL, "OFF"); - envConfig.setLoggingHandler(new Log4jLoggingHandler("["+configuration.getName()+"]")); - - Map<String, String> params = new HashMap<>(EnvironmentFacade.ENVCONFIG_DEFAULTS); - params.putAll(configuration.getParameters()); - - for (Map.Entry<String, String> configItem : params.entrySet()) - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Setting EnvironmentConfig key " - + configItem.getKey() - + " to '" - + configItem.getValue() - + "'"); - } - envConfig.setConfigParam(configItem.getKey(), configItem.getValue()); - } - - envConfig.setExceptionListener(new LoggingAsyncExceptionListener()); - - EnvHomeRegistry.getInstance().registerHome(_environmentPath); - - boolean success = false; - try - { - _environment = new Environment(_environmentPath, envConfig); - success = true; - } - finally - { - if (!success) - { - EnvHomeRegistry.getInstance().deregisterHome(_environmentPath); - } - } - - _committer = new CoalescingCommiter(name, this); - _committer.start(); - } - - - @Override - public Transaction beginTransaction() - { - return _environment.beginTransaction(null, null); - } - - @Override - public FutureResult commit(com.sleepycat.je.Transaction tx, boolean syncCommit) - { - try - { - tx.commitNoSync(); - } - catch (DatabaseException de) - { - LOGGER.error("Got DatabaseException on commit, closing environment", de); - - closeEnvironmentSafely(); - - throw handleDatabaseException("Got DatabaseException on commit", de); - } - return _committer.commit(tx, syncCommit); - } - - @Override - public void close() - { - try - { - _committer.stop(); - - closeSequences(); - closeDatabases(); - } - finally - { - try - { - closeEnvironment(); - } - finally - { - EnvHomeRegistry.getInstance().deregisterHome(_environmentPath); - } - } - } - - private void closeSequences() - { - RuntimeException firstThrownException = null; - for (DatabaseEntry sequenceKey : _cachedSequences.keySet()) - { - try - { - closeSequence(sequenceKey); - } - catch(DatabaseException de) - { - if (firstThrownException == null) - { - firstThrownException = de; - } - } - } - if (firstThrownException != null) - { - throw firstThrownException; - } - } - - private void closeDatabases() - { - RuntimeException firstThrownException = null; - for (String databaseName : _cachedDatabases.keySet()) - { - try - { - closeDatabase(databaseName); - } - catch(DatabaseException 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 - { - BDBUtils.runCleaner(_environment); - } - finally - { - _environment.close(); - _environment = null; - } - } - } - - @Override - public RuntimeException handleDatabaseException(String contextMessage, RuntimeException e) - { - if (_environment != null && !_environment.isValid()) - { - closeEnvironmentSafely(); - } - if (e instanceof StoreException) - { - return e; - } - return new StoreException("Unexpected exception occurred on store operation", e); - } - - @Override - public Database openDatabase(String name, DatabaseConfig databaseConfig) - { - Database cachedHandle = _cachedDatabases.get(name); - if (cachedHandle == null) - { - Database handle = _environment.openDatabase(null, name, databaseConfig); - Database existingHandle = _cachedDatabases.putIfAbsent(name, handle); - if (existingHandle == null) - { - cachedHandle = handle; - } - else - { - cachedHandle = existingHandle; - handle.close(); - } - } - return cachedHandle; - } - - - @Override - public Database clearDatabase(String name, DatabaseConfig databaseConfig) - { - closeDatabase(name); - _environment.removeDatabase(null, name); - return openDatabase(name, databaseConfig); - } - - @Override - public Sequence openSequence(final Database database, - final DatabaseEntry sequenceKey, - final SequenceConfig sequenceConfig) - { - Sequence cachedSequence = _cachedSequences.get(sequenceKey); - if (cachedSequence == null) - { - Sequence handle = database.openSequence(null, sequenceKey, sequenceConfig); - Sequence existingHandle = _cachedSequences.putIfAbsent(sequenceKey, handle); - if (existingHandle == null) - { - cachedSequence = handle; - } - else - { - cachedSequence = existingHandle; - handle.close(); - } - } - return cachedSequence; - } - - - private void closeSequence(final DatabaseEntry sequenceKey) - { - Sequence cachedHandle = _cachedSequences.remove(sequenceKey); - if (cachedHandle != null) - { - cachedHandle.close(); - } - } - - @Override - public void closeDatabase(final String name) - { - Database cachedHandle = _cachedDatabases.remove(name); - if (cachedHandle != null) - { - cachedHandle.close(); - } - } - - @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 deleted file mode 100644 index 6d3238728e..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacadeFactory.java +++ /dev/null @@ -1,82 +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.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import com.sleepycat.je.config.ConfigParam; -import com.sleepycat.je.config.EnvironmentParams; - -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.store.FileBasedSettings; - -public class StandardEnvironmentFacadeFactory implements EnvironmentFacadeFactory -{ - @SuppressWarnings("unchecked") - @Override - public EnvironmentFacade createEnvironmentFacade(final ConfiguredObject<?> parent) - { - final FileBasedSettings settings = (FileBasedSettings)parent; - final String storeLocation = settings.getStorePath(); - - StandardEnvironmentConfiguration sec = new StandardEnvironmentConfiguration() - { - @Override - public String getName() - { - return parent.getName(); - } - - @Override - public String getStorePath() - { - return storeLocation; - } - - @Override - public Map<String, String> getParameters() - { - return buildEnvironmentConfiguration(parent); - } - }; - - return new StandardEnvironmentFacade(sec); - } - - private Map<String, String> buildEnvironmentConfiguration(ConfiguredObject<?> parent) - { - Map<String, String> envConfigMap = new HashMap<>(); - - for (ConfigParam cp : EnvironmentParams.SUPPORTED_PARAMS.values()) - { - final String parameterName = cp.getName(); - Set<String> contextKeys = parent.getContextKeys(false); - if (!cp.isForReplication() && contextKeys.contains(parameterName)) - { - envConfigMap.put(parameterName, parent.getContextValue(String.class, parameterName)); - } - } - return Collections.unmodifiableMap(envConfigMap); - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/entry/HierarchyKey.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/entry/HierarchyKey.java deleted file mode 100644 index d1c341447e..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/entry/HierarchyKey.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.berkeleydb.entry; - -import java.util.UUID; - -public class HierarchyKey -{ - private final UUID _childId; - private final String _parentType; - - public HierarchyKey(final UUID childId, final String parentType) - { - _childId = childId; - _parentType = parentType; - } - - public UUID getChildId() - { - return _childId; - } - - public String getParentType() - { - return _parentType; - } - - @Override - public boolean equals(final Object o) - { - if (this == o) - { - return true; - } - if (o == null || getClass() != o.getClass()) - { - return false; - } - - final HierarchyKey that = (HierarchyKey) o; - - if (!_childId.equals(that._childId)) - { - return false; - } - if (!_parentType.equals(that._parentType)) - { - return false; - } - - return true; - } - - @Override - public int hashCode() - { - int result = _childId.hashCode(); - result = 31 * result + _parentType.hashCode(); - return result; - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/entry/PreparedTransaction.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/entry/PreparedTransaction.java deleted file mode 100644 index 9ecc5b3283..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/entry/PreparedTransaction.java +++ /dev/null @@ -1,46 +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.entry; - -import org.apache.qpid.server.store.Transaction; - -public class PreparedTransaction -{ - private final Transaction.EnqueueRecord[] _enqueues; - private final Transaction.DequeueRecord[] _dequeues; - - public PreparedTransaction(Transaction.EnqueueRecord[] enqueues, Transaction.DequeueRecord[] dequeues) - { - _enqueues = enqueues; - _dequeues = dequeues; - } - - public Transaction.EnqueueRecord[] getEnqueues() - { - return _enqueues; - } - - public Transaction.DequeueRecord[] getDequeues() - { - return _dequeues; - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/entry/QueueEntryKey.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/entry/QueueEntryKey.java deleted file mode 100644 index e7cf93ff7a..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/entry/QueueEntryKey.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.entry; - -import java.util.UUID; - -public class QueueEntryKey -{ - private UUID _queueId; - private long _messageId; - - public QueueEntryKey(UUID queueId, long messageId) - { - _queueId = queueId; - _messageId = messageId; - } - - public UUID getQueueId() - { - return _queueId; - } - - public long getMessageId() - { - return _messageId; - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/logging/Log4jLoggingHandler.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/logging/Log4jLoggingHandler.java deleted file mode 100644 index 6b952d53dd..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/logging/Log4jLoggingHandler.java +++ /dev/null @@ -1,231 +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.logging; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.logging.ErrorManager; -import java.util.logging.Formatter; -import java.util.logging.Handler; -import java.util.logging.Level; -import java.util.logging.LogRecord; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -public class Log4jLoggingHandler extends Handler -{ - public Log4jLoggingHandler(final String prefix) - { - setFormatter(new Formatter() - { - @Override - public String format(final LogRecord record) - { - return prefix + " " + formatMessage(record); - } - }); - } - - private static interface MappedLevel - { - public boolean isEnabled(final Logger logger); - - void log(Logger logger, String message); - } - - private static final MappedLevel ERROR = new MappedLevel() - { - @Override - public boolean isEnabled(final Logger logger) - { - return logger.isErrorEnabled(); - } - - @Override - public void log(final Logger logger, final String message) - { - logger.error(message); - } - }; - - private static final MappedLevel WARN = new MappedLevel() - { - @Override - public boolean isEnabled(final Logger logger) - { - return logger.isWarnEnabled(); - } - - @Override - public void log(final Logger logger, final String message) - { - logger.warn(message); - } - }; - - private static final MappedLevel INFO = new MappedLevel() - { - @Override - public boolean isEnabled(final Logger logger) - { - return logger.isInfoEnabled(); - } - - @Override - public void log(final Logger logger, final String message) - { - logger.info(message); - } - }; - - private static final MappedLevel DEBUG = new MappedLevel() - { - @Override - public boolean isEnabled(final Logger logger) - { - return logger.isDebugEnabled(); - } - - @Override - public void log(final Logger logger, final String message) - { - logger.debug(message); - } - }; - - private static final MappedLevel TRACE = new MappedLevel() - { - @Override - public boolean isEnabled(final Logger logger) - { - return logger.isTraceEnabled(); - } - - @Override - public void log(final Logger logger, final String message) - { - logger.trace(message); - } - }; - - private static final Map<Level, MappedLevel> LEVEL_MAP; - static - { - Map<Level, MappedLevel> map = new HashMap<>(); - map.put(Level.SEVERE, ERROR); - map.put(Level.WARNING, WARN); - //Note that INFO comes out at DEBUG level as the BDB logging at INFO seems to be more of a DEBUG nature - map.put(Level.INFO, DEBUG); - map.put(Level.CONFIG, DEBUG); - map.put(Level.FINE, TRACE); - map.put(Level.FINER, TRACE); - map.put(Level.FINEST, TRACE); - map.put(Level.ALL, TRACE); - - LEVEL_MAP = Collections.unmodifiableMap(map); - } - - private static final Logger BDB_LOGGER = LoggerFactory.getLogger("BDB"); - - private boolean isEnabledFor(Level level) - { - final MappedLevel mappedLevel = LEVEL_MAP.get(level); - return mappedLevel == null ? false : mappedLevel.isEnabled(BDB_LOGGER); - } - - @Override - public void publish(final LogRecord record) - { - MappedLevel level = convertLevel(record.getLevel()); - if (level.isEnabled(BDB_LOGGER)) - { - - Formatter formatter = getFormatter(); - - try - { - String message = formatter.format(record); - try - { - level.log(BDB_LOGGER, message); - } - catch (RuntimeException e) - { - reportError(null, e, ErrorManager.WRITE_FAILURE); - } - } - catch (RuntimeException e) - { - reportError(null, e, ErrorManager.FORMAT_FAILURE); - } - } - } - - @Override - public boolean isLoggable(final LogRecord record) - { - MappedLevel mappedLevel = convertLevel(record.getLevel()); - - return mappedLevel.isEnabled(BDB_LOGGER); - } - - private MappedLevel convertLevel(final Level level) - { - //Note that INFO comes out at DEBUG level as the BDB logging at INFO seems to be more of a DEBUG nature - MappedLevel result = LEVEL_MAP.get(level); - if(result == null) - { - if (level.intValue() >= Level.SEVERE.intValue()) - { - result = ERROR; - } - else if (level.intValue() >= Level.WARNING.intValue()) - { - result = WARN; - } - else if (level.intValue() >= Level.CONFIG.intValue()) - { - result = DEBUG; - } - else - { - result = TRACE; - } - } - - return result; - } - - @Override - public void flush() - { - - } - - @Override - public void close() throws SecurityException - { - - } -} 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 deleted file mode 100644 index ef522a4594..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/DatabasePinger.java +++ /dev/null @@ -1,99 +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.replication; - -import com.sleepycat.bind.tuple.IntegerBinding; -import com.sleepycat.bind.tuple.LongBinding; -import com.sleepycat.je.Database; -import com.sleepycat.je.DatabaseConfig; -import com.sleepycat.je.DatabaseEntry; -import com.sleepycat.je.Durability; -import com.sleepycat.je.Transaction; -import com.sleepycat.je.TransactionConfig; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.server.store.berkeleydb.EnvironmentFacade; - -public class DatabasePinger -{ - private static final Logger LOGGER = LoggerFactory.getLogger(DatabasePinger.class); - - public static final String PING_DATABASE_NAME = "PINGDB"; - private static final DatabaseConfig DATABASE_CONFIG = - DatabaseConfig.DEFAULT.setAllowCreate(true).setTransactional(true); - private static final int ID = 0; - private final TransactionConfig _pingTransactionConfig = new TransactionConfig(); - - public DatabasePinger() - { - // The ping merely needs to establish that the sufficient remote nodes are available, - // we don't need to await the data being written/synch'd - _pingTransactionConfig.setDurability(new Durability(Durability.SyncPolicy.NO_SYNC, - Durability.SyncPolicy.NO_SYNC, - Durability.ReplicaAckPolicy.SIMPLE_MAJORITY)); - } - - public void pingDb(EnvironmentFacade facade) - { - try - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Beginning ping transaction"); - } - - final Database db = facade.openDatabase(PING_DATABASE_NAME, - DATABASE_CONFIG); - - 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, _pingTransactionConfig); - db.put(txn, key, value); - txn.commit(); - - txn = null; - } - finally - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Ping transaction completed"); - } - - if (txn != null) - { - txn.abort(); - } - } - } - catch (RuntimeException 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 deleted file mode 100644 index 18b9727a61..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentConfiguration.java +++ /dev/null @@ -1,39 +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.replication; - -import java.util.Map; - -import org.apache.qpid.server.store.berkeleydb.StandardEnvironmentConfiguration; - -public interface ReplicatedEnvironmentConfiguration extends StandardEnvironmentConfiguration -{ - String getGroupName(); - String getHostPort(); - String getHelperHostPort(); - boolean isDesignatedPrimary(); - int getPriority(); - int getQuorumOverride(); - Map<String, String> getReplicationParameters(); - String getHelperNodeName(); - int getFacadeParameter(String parameterName, int defaultValue); -} 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 deleted file mode 100644 index e16ed737af..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java +++ /dev/null @@ -1,1909 +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.replication; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -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.CopyOnWriteArraySet; -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 com.sleepycat.je.Database; -import com.sleepycat.je.DatabaseConfig; -import com.sleepycat.je.DatabaseEntry; -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.EnvironmentConfig; -import com.sleepycat.je.EnvironmentFailureException; -import com.sleepycat.je.ExceptionEvent; -import com.sleepycat.je.LogWriteException; -import com.sleepycat.je.Sequence; -import com.sleepycat.je.SequenceConfig; -import com.sleepycat.je.Transaction; -import com.sleepycat.je.TransactionConfig; -import com.sleepycat.je.rep.*; -import com.sleepycat.je.rep.impl.node.NameIdPair; -import com.sleepycat.je.rep.util.DbPing; -import com.sleepycat.je.rep.util.ReplicationGroupAdmin; -import com.sleepycat.je.rep.utilint.HostPortPair; -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; -import org.codehaus.jackson.map.ObjectMapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.server.configuration.IllegalConfigurationException; -import org.apache.qpid.server.store.StoreException; -import org.apache.qpid.server.util.FutureResult; -import org.apache.qpid.server.store.berkeleydb.BDBUtils; -import org.apache.qpid.server.store.berkeleydb.CoalescingCommiter; -import org.apache.qpid.server.store.berkeleydb.EnvHomeRegistry; -import org.apache.qpid.server.store.berkeleydb.EnvironmentFacade; -import org.apache.qpid.server.store.berkeleydb.logging.Log4jLoggingHandler; -import org.apache.qpid.server.util.ConnectionScopedRuntimeException; -import org.apache.qpid.server.util.DaemonThreadFactory; -import org.apache.qpid.server.util.ServerScopedRuntimeException; - -public class ReplicatedEnvironmentFacade implements EnvironmentFacade, StateChangeListener -{ - public static final String MASTER_TRANSFER_TIMEOUT_PROPERTY_NAME = "qpid.bdb.ha.master_transfer_interval"; - 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"; - public static final String ENVIRONMENT_RESTART_RETRY_LIMIT_PROPERTY_NAME = "qpid.bdb.ha.environment_restart_retry_limit"; - public static final String EXECUTOR_SHUTDOWN_TIMEOUT_PROPERTY_NAME = "qpid.bdb.ha.executor_shutdown_timeout"; - - private static final Logger LOGGER = LoggerFactory.getLogger(ReplicatedEnvironmentFacade.class); - - private static final int DEFAULT_MASTER_TRANSFER_TIMEOUT = 1000 * 60; - private static final int DEFAULT_DB_PING_SOCKET_TIMEOUT = 1000; - private static final int DEFAULT_REMOTE_NODE_MONITOR_INTERVAL = 1000; - private static final int DEFAULT_ENVIRONMENT_RESTART_RETRY_LIMIT = 3; - private static final int DEFAULT_EXECUTOR_SHUTDOWN_TIMEOUT = 5000; - - /** Length of time allowed for a master transfer to complete before the operation will timeout */ - private final int _masterTransferTimeout; - - /** - * Qpid monitors the health of the other nodes in the group. This controls the length of time - * between each scan of the all the nodes. - */ - private final int _remoteNodeMonitorInterval; - - /** - * Qpid uses DbPing to establish the health of other nodes in the group. This controls the socket timeout - * (so_timeout) used on the socket underlying DbPing. - */ - private final int _dbPingSocketTimeout; - - /** - * If the environment creation fails, Qpid will automatically retry. This controls the number - * of times recreation will be attempted. - */ - private final int _environmentRestartRetryLimit; - - /** - * Length of time for executors used by facade to shutdown gracefully - */ - private final int _executorShutdownTimeout; - - static final SyncPolicy LOCAL_TRANSACTION_SYNCHRONIZATION_POLICY = SyncPolicy.SYNC; - static final SyncPolicy REMOTE_TRANSACTION_SYNCHRONIZATION_POLICY = SyncPolicy.NO_SYNC; - public static final ReplicaAckPolicy REPLICA_REPLICA_ACKNOWLEDGMENT_POLICY = ReplicaAckPolicy.SIMPLE_MAJORITY; - - @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, "180 s"); - /** - * 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"); - - /** - * Allow Replica to proceed with transactions regardless of the state of a Replica - * At the moment we do not read or write databases on Replicas. - * Setting consistency policy to NoConsistencyRequiredPolicy - * would allow to create transaction on Replica immediately. - * Any followed write operation would fail with ReplicaWriteException. - */ - put(ReplicationConfig.CONSISTENCY_POLICY, NoConsistencyRequiredPolicy.NAME); - }}); - - public static final String PERMITTED_NODE_LIST = "permittedNodes"; - - private final ReplicatedEnvironmentConfiguration _configuration; - private final String _prettyGroupNodeName; - private final File _environmentDirectory; - - private final ExecutorService _environmentJobExecutor; - private final ExecutorService _stateChangeExecutor; - private final ScheduledExecutorService _groupChangeExecutor; - private final AtomicReference<State> _state = new AtomicReference<State>(State.OPENING); - private final ConcurrentMap<String, ReplicationNode> _remoteReplicationNodes = new ConcurrentHashMap<String, ReplicationNode>(); - private final AtomicReference<ReplicationGroupListener> _replicationGroupListener = new AtomicReference<ReplicationGroupListener>(); - private final AtomicReference<StateChangeListener> _stateChangeListener = new AtomicReference<StateChangeListener>(); - private final Durability _defaultDurability; - private final ConcurrentMap<String, Database> _cachedDatabases = new ConcurrentHashMap<>(); - private final ConcurrentMap<DatabaseEntry, Sequence> _cachedSequences = new ConcurrentHashMap<>(); - private final Set<String> _permittedNodes = new CopyOnWriteArraySet<String>(); - - private volatile Durability _realMessageStoreDurability = null; - private volatile Durability _messageStoreDurability; - private volatile CoalescingCommiter _coalescingCommiter = null; - private volatile ReplicatedEnvironment _environment; - private volatile long _joinTime; - private volatile ReplicatedEnvironment.State _lastKnownEnvironmentState; - private volatile long _envSetupTimeoutMillis; - /** Flag set true when JE need to discard transactions in order to rejoin the group */ - private volatile boolean _nodeRolledback; - - 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."); - } - } - else - { - LOGGER.debug("Environment at path " + _environmentDirectory + " already exists."); - } - - _configuration = configuration; - - _masterTransferTimeout = configuration.getFacadeParameter(MASTER_TRANSFER_TIMEOUT_PROPERTY_NAME, DEFAULT_MASTER_TRANSFER_TIMEOUT); - _dbPingSocketTimeout = configuration.getFacadeParameter(DB_PING_SOCKET_TIMEOUT_PROPERTY_NAME, DEFAULT_DB_PING_SOCKET_TIMEOUT); - _remoteNodeMonitorInterval = configuration.getFacadeParameter(REMOTE_NODE_MONITOR_INTERVAL_PROPERTY_NAME, DEFAULT_REMOTE_NODE_MONITOR_INTERVAL); - _environmentRestartRetryLimit = configuration.getFacadeParameter(ENVIRONMENT_RESTART_RETRY_LIMIT_PROPERTY_NAME, DEFAULT_ENVIRONMENT_RESTART_RETRY_LIMIT); - _executorShutdownTimeout = configuration.getFacadeParameter(EXECUTOR_SHUTDOWN_TIMEOUT_PROPERTY_NAME, DEFAULT_EXECUTOR_SHUTDOWN_TIMEOUT); - - _defaultDurability = new Durability(LOCAL_TRANSACTION_SYNCHRONIZATION_POLICY, REMOTE_TRANSACTION_SYNCHRONIZATION_POLICY, REPLICA_REPLICA_ACKNOWLEDGMENT_POLICY); - _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)); - _stateChangeExecutor = Executors.newSingleThreadExecutor(new DaemonThreadFactory("StateChange-" + _prettyGroupNodeName)); - _groupChangeExecutor = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors() + 1, new DaemonThreadFactory("Group-Change-Learner:" + _prettyGroupNodeName)); - - // create environment in a separate thread to avoid renaming of the current thread by JE - EnvHomeRegistry.getInstance().registerHome(_environmentDirectory); - boolean success = false; - try - { - createEnvironment(true); - success = true; - } - finally - { - if (!success) - { - EnvHomeRegistry.getInstance().deregisterHome(_environmentDirectory); - } - } - populateExistingRemoteReplicationNodes(); - _groupChangeExecutor.submit(new RemoteNodeStateLearner()); - } - - @Override - public Transaction beginTransaction() - { - if (_messageStoreDurability == null) - { - throw new IllegalStateException("Message store durability is not set"); - } - - try - { - TransactionConfig transactionConfig = new TransactionConfig(); - transactionConfig.setDurability(getRealMessageStoreDurability()); - return _environment.beginTransaction(null, transactionConfig); - } - catch(DatabaseException e) - { - throw handleDatabaseException("Failure to start transaction", e); - } - } - - @Override - public FutureResult commit(final Transaction tx, boolean syncCommit) - { - try - { - // Using commit() instead of commitNoSync() for the HA store to allow - // the HA durability configuration to influence resulting behaviour. - tx.commit(_realMessageStoreDurability); - } - catch (DatabaseException de) - { - throw handleDatabaseException("Got DatabaseException on commit, closing environment", de); - } - - if (_coalescingCommiter != null && _realMessageStoreDurability.getLocalSync() == SyncPolicy.NO_SYNC - && _messageStoreDurability.getLocalSync() == SyncPolicy.SYNC) - { - return _coalescingCommiter.commit(tx, syncCommit); - } - return FutureResult.IMMEDIATE_FUTURE; - } - - @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()); - } - - long timeout = Math.max(_executorShutdownTimeout, _envSetupTimeoutMillis); - shutdownAndAwaitExecutorService(_environmentJobExecutor, - timeout, - TimeUnit.MILLISECONDS); - shutdownAndAwaitExecutorService(_groupChangeExecutor, _executorShutdownTimeout, TimeUnit.MILLISECONDS); - shutdownAndAwaitExecutorService(_stateChangeExecutor, _executorShutdownTimeout, TimeUnit.MILLISECONDS); - - try - { - if (_coalescingCommiter != null) - { - _coalescingCommiter.stop(); - } - closeSequences(); - closeDatabases(); - } - finally - { - try - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Closing replicated environment"); - } - - closeEnvironment(); - } - finally - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Deregistering environment home " + _environmentDirectory); - } - - EnvHomeRegistry.getInstance().deregisterHome(_environmentDirectory); - } - } - } - finally - { - _state.compareAndSet(State.CLOSING, State.CLOSED); - } - } - } - - private void shutdownAndAwaitExecutorService(ExecutorService executorService, long executorShutdownTimeout, TimeUnit timeUnit) - { - executorService.shutdown(); - try - { - boolean wasShutdown = executorService.awaitTermination(executorShutdownTimeout, timeUnit); - if (!wasShutdown) - { - LOGGER.warn("Executor service " + executorService + - " did not shutdown within allowed time period " + _executorShutdownTimeout - + " " + timeUnit + ", ignoring"); - } - } - catch (InterruptedException e) - { - Thread.currentThread().interrupt(); - LOGGER.warn("Shutdown of executor service " + executorService + " was interrupted"); - } - } - - @Override - public RuntimeException handleDatabaseException(String contextMessage, final RuntimeException dbe) - { - if (dbe instanceof LogWriteException) - { - // something wrong with the disk (for example, no space left on device) - // store cannot operate - throw new ServerScopedRuntimeException("Cannot save data into the store", dbe); - } - - if (dbe instanceof StoreException || dbe instanceof ConnectionScopedRuntimeException) - { - return dbe; - } - else if (dbe instanceof DatabaseException) - { - boolean noMajority = dbe instanceof InsufficientReplicasException || dbe instanceof InsufficientAcksException; - - if (noMajority) - { - ReplicationGroupListener listener = _replicationGroupListener.get(); - if (listener != null) - { - listener.onNoMajority(); - } - } - - if (dbe instanceof UnknownMasterException) - { - // when Master transits into Unknown state ( for example, due to mastership transfer) - // we need to abort any ongoing je operation without halting the Broker or VHN/VH - return new ConnectionScopedRuntimeException(String.format("Environment '%s' cannot finish JE operation because master is unknown", getNodeName()), dbe); - } - - if (dbe instanceof ReplicaWriteException || dbe instanceof ReplicaConsistencyException) - { - // Master transited into Detached/Replica but underlying Configured Object has not been notified yet - // and attempted to perform JE operation. - // We need to abort any ongoing JE operation without halting the Broker or VHN/VH - return new ConnectionScopedRuntimeException(String.format("Environment '%s' cannot finish JE operation because node is not master", getNodeName()), dbe); - } - - boolean restart = (noMajority || dbe instanceof RestartRequiredException); - if (restart) - { - tryToRestartEnvironment((DatabaseException)dbe); - return new ConnectionScopedRuntimeException(noMajority ? "Required number of nodes not reachable" : "Underlying JE environment is being restarted", dbe); - } - } - else - { - if (dbe instanceof IllegalStateException && getFacadeState() == State.RESTARTING) - { - return new ConnectionScopedRuntimeException("Underlying JE environment is being restarted", dbe); - } - } - return new StoreException("Unexpected exception occurred in replicated environment", dbe); - } - - private void tryToRestartEnvironment(final DatabaseException dbe) - { - if (_state.compareAndSet(State.OPEN, State.RESTARTING) || _state.compareAndSet(State.OPENING, 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() - { - int attemptNumber = 1; - boolean restarted = false; - while(_state.get() == State.RESTARTING && attemptNumber <= _environmentRestartRetryLimit) - { - try - { - restartEnvironment(); - restarted = true; - break; - } - catch(EnvironmentFailureException e) - { - LOGGER.warn("Failure whilst trying to restart environment (attempt number " - + attemptNumber + " of " + _environmentRestartRetryLimit + ")", e); - } - catch (Exception e) - { - LOGGER.error("Fatal failure whilst trying to restart environment", e); - break; - } - attemptNumber++; - } - - if (!restarted) - { - LOGGER.warn("Failed to restart environment."); - } - } - }); - } - else - { - LOGGER.info("Cannot restart environment because of facade state: " + _state.get()); - } - } - - @Override - public Database openDatabase(String name, DatabaseConfig databaseConfig) - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("openDatabase " + name + " for " + _prettyGroupNodeName); - } - if (_state.get() != State.OPEN) - { - throw new ConnectionScopedRuntimeException("Environment facade is not in opened state"); - } - - if (!_environment.isValid()) - { - throw new ConnectionScopedRuntimeException("Environment is not valid"); - } - - Database cachedHandle = _cachedDatabases.get(name); - if (cachedHandle == null) - { - Database handle = _environment.openDatabase(null, name, databaseConfig); - Database existingHandle = _cachedDatabases.putIfAbsent(name, handle); - if (existingHandle == null) - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("openDatabase " + name + " new handle"); - } - - cachedHandle = handle; - } - else - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("openDatabase " + name + " existing handle"); - } - cachedHandle = existingHandle; - handle.close(); - } - } - return cachedHandle; - } - - - @Override - public Database clearDatabase(String name, DatabaseConfig databaseConfig) - { - closeDatabase(name); - _environment.removeDatabase(null, name); - return openDatabase(name, databaseConfig); - } - - @Override - public void closeDatabase(final String databaseName) - { - Database cachedHandle = _cachedDatabases.remove(databaseName); - if (cachedHandle != null) - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Closing " + databaseName + " on " + _prettyGroupNodeName); - } - if (cachedHandle.getEnvironment().isValid()) - { - cachedHandle.close(); - } - } - } - @Override - public Sequence openSequence(final Database database, - final DatabaseEntry sequenceKey, - final SequenceConfig sequenceConfig) - { - Sequence cachedSequence = _cachedSequences.get(sequenceKey); - if (cachedSequence == null) - { - Sequence handle = database.openSequence(null, sequenceKey, sequenceConfig); - Sequence existingHandle = _cachedSequences.putIfAbsent(sequenceKey, handle); - if (existingHandle == null) - { - cachedSequence = handle; - } - else - { - cachedSequence = existingHandle; - handle.close(); - } - } - return cachedSequence; - } - - - private void closeSequence(final DatabaseEntry sequenceKey) - { - Sequence cachedHandle = _cachedSequences.remove(sequenceKey); - if (cachedHandle != null) - { - cachedHandle.close(); - } - } - - @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) - { - _stateChangeExecutor.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(); - } - } - - 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; - } - - 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(); - } - - Durability getRealMessageStoreDurability() - { - return _realMessageStoreDurability; - } - - public Durability getMessageStoreDurability() - { - return _messageStoreDurability; - } - - public boolean isCoalescingSync() - { - return _coalescingCommiter != null; - } - - 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 Future<Void> transferMasterToSelfAsynchronously() - { - final String nodeName = getNodeName(); - return transferMasterAsynchronously(nodeName); - } - - public Future<Void> transferMasterAsynchronously(final String nodeName) - { - return _groupChangeExecutor.submit(new Callable<Void>() - { - @Override - public Void call() throws Exception - { - try - { - ReplicationGroupAdmin admin = createReplicationGroupAdmin(); - String newMaster = admin.transferMaster(Collections.singleton(nodeName), - _masterTransferTimeout, TimeUnit.MILLISECONDS, true); - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("The mastership has been transferred to " + newMaster); - } - } - catch (DatabaseException e) - { - LOGGER.warn("Exception on transferring the mastership to " + _prettyGroupNodeName - + " Master transfer timeout : " + _masterTransferTimeout, e); - throw e; - } - return null; - } - }); - } - - public void removeNodeFromGroup(final String nodeName) - { - createReplicationGroupAdmin().removeMember(nodeName); - } - - 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; - } - } - - private ReplicationGroupAdmin createReplicationGroupAdmin() - { - final Set<InetSocketAddress> helpers = new HashSet<InetSocketAddress>(); - helpers.addAll(_environment.getRepConfig().getHelperSockets()); - - final ReplicationConfig repConfig = _environment.getRepConfig(); - helpers.add(HostPortPair.getSocket(HostPortPair.getString(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() - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Closing JE environment for " + _prettyGroupNodeName); - } - - // 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()) - { - BDBUtils.runCleaner(_environment); - } - } - finally - { - // Try closing the environment but swallow EnvironmentFailureException - // if the environment becomes invalid while closing. - // This can be caused by potential race between facade close and DatabasePinger open. - try - { - _environment.close(); - } - catch (EnvironmentFailureException efe) - { - if (!_environment.isValid()) - { - LOGGER.debug("Environment became invalid on close, so ignore", efe); - } - else - { - throw efe; - } - } - finally - { - _environment = null; - } - } - } - - private void restartEnvironment() - { - LOGGER.info("Restarting environment"); - - StateChangeListener stateChangeListener = _stateChangeListener.get(); - - if (stateChangeListener != null) - { - _stateChangeExecutor.submit(new Runnable() - { - @Override - public void run() - { - StateChangeEvent detached = new StateChangeEvent(ReplicatedEnvironment.State.DETACHED, NameIdPair.NULL); - stateChanged(detached); - } - }); - } - - closeEnvironmentOnRestart(); - - createEnvironment(false); - - if (stateChangeListener != null) - { - _environment.setStateChangeListener(this); - } - - LOGGER.info("Environment is restarted"); - } - - private void closeEnvironmentOnRestart() - { - ReplicatedEnvironment environment = _environment; - if (environment != null) - { - try - { - try - { - closeSequences(); - 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 closeSequences() - { - RuntimeException firstThrownException = null; - for (DatabaseEntry sequenceKey : _cachedSequences.keySet()) - { - try - { - closeSequence(sequenceKey); - } - catch(DatabaseException de) - { - if (firstThrownException == null) - { - firstThrownException = de; - } - } - } - if (firstThrownException != null) - { - throw firstThrownException; - } - } - - private void closeDatabases() - { - RuntimeException firstThrownException = null; - - Iterator<String> itr = _cachedDatabases.keySet().iterator(); - while (itr.hasNext()) - { - String databaseName = itr.next(); - - if (databaseName != null) - { - try - { - closeDatabase(databaseName); - } - catch(RuntimeException e) - { - LOGGER.error("Failed to close database " + databaseName + " on " + _prettyGroupNodeName, e); - if (firstThrownException == null) - { - firstThrownException = e; - } - } - } - } - - if (firstThrownException != null) - { - throw firstThrownException; - } - } - - private void createEnvironment(boolean createEnvironmentInSeparateThread) - { - String groupName = _configuration.getGroupName(); - String helperHostPort = _configuration.getHelperHostPort(); - String hostPort = _configuration.getHostPort(); - boolean designatedPrimary = _configuration.isDesignatedPrimary(); - int priority = _configuration.getPriority(); - int quorumOverride = _configuration.getQuorumOverride(); - String nodeName = _configuration.getName(); - String helperNodeName = _configuration.getHelperNodeName(); - - if (LOGGER.isInfoEnabled()) - { - LOGGER.info("Creating environment"); - LOGGER.info("Environment path " + _environmentDirectory.getAbsolutePath()); - LOGGER.info("Group name " + groupName); - LOGGER.info("Node name " + nodeName); - LOGGER.info("Node host port " + hostPort); - LOGGER.info("Helper host port " + helperHostPort); - LOGGER.info("Helper node name " + helperNodeName); - LOGGER.info("Durability " + _defaultDurability); - LOGGER.info("Designated primary (applicable to 2 node case only) " + designatedPrimary); - LOGGER.info("Node priority " + priority); - LOGGER.info("Quorum override " + quorumOverride); - LOGGER.info("Permitted node list " + _permittedNodes); - } - - Map<String, String> replicationEnvironmentParameters = new HashMap<>(ReplicatedEnvironmentFacade.REPCONFIG_DEFAULTS); - replicationEnvironmentParameters.putAll(_configuration.getReplicationParameters()); - - ReplicationConfig replicationConfig = new ReplicationConfig(groupName, nodeName, hostPort); - replicationConfig.setHelperHosts(helperHostPort); - replicationConfig.setDesignatedPrimary(designatedPrimary); - replicationConfig.setNodePriority(priority); - replicationConfig.setElectableGroupSizeOverride(quorumOverride); - - for (Map.Entry<String, String> configItem : replicationEnvironmentParameters.entrySet()) - { - if (LOGGER.isInfoEnabled()) - { - LOGGER.info("Setting ReplicationConfig key " + configItem.getKey() + " to '" + configItem.getValue() + "'"); - } - replicationConfig.setConfigParam(configItem.getKey(), configItem.getValue()); - } - - Map<String, String> environmentParameters = new HashMap<>(EnvironmentFacade.ENVCONFIG_DEFAULTS); - environmentParameters.putAll(_configuration.getParameters()); - - EnvironmentConfig envConfig = new EnvironmentConfig(); - envConfig.setAllowCreate(true); - envConfig.setTransactional(true); - envConfig.setExceptionListener(new ExceptionListener()); - envConfig.setDurability(_defaultDurability); - - envConfig.setConfigParam(EnvironmentConfig.FILE_LOGGING_LEVEL, "OFF"); - envConfig.setConfigParam(EnvironmentConfig.CONSOLE_LOGGING_LEVEL, "OFF"); - envConfig.setLoggingHandler(new Log4jLoggingHandler("[" + _configuration.getName() + "]")); - - for (Map.Entry<String, String> configItem : environmentParameters.entrySet()) - { - if (LOGGER.isInfoEnabled()) - { - LOGGER.info("Setting EnvironmentConfig key " + configItem.getKey() + " to '" + configItem.getValue() + "'"); - } - envConfig.setConfigParam(configItem.getKey(), configItem.getValue()); - } - - if (createEnvironmentInSeparateThread) - { - createEnvironmentInSeparateThread(_environmentDirectory, envConfig, replicationConfig); - } - else - { - createEnvironment(_environmentDirectory, envConfig, replicationConfig); - } - } - - private void createEnvironmentInSeparateThread(final File environmentPathFile, final EnvironmentConfig envConfig, - final ReplicationConfig replicationConfig) - { - Future<Void> environmentFuture = _environmentJobExecutor.submit(new Callable<Void>(){ - @Override - public Void call() throws Exception - { - createEnvironment(environmentPathFile, envConfig, replicationConfig); - return null; - }}); - - final long setUpTimeOutMillis = extractEnvSetupTimeoutMillis(replicationConfig); - final long initialTimeOutMillis = Math.max(setUpTimeOutMillis / 4, 1000); - final long remainingTimeOutMillis = setUpTimeOutMillis - initialTimeOutMillis; - try - { - try - { - environmentFuture.get(initialTimeOutMillis, TimeUnit.MILLISECONDS); - } - catch (TimeoutException te) - { - if (remainingTimeOutMillis > 0) - { - LOGGER.warn("Slow replicated environment creation for " + _prettyGroupNodeName - + ". Will continue to wait for further " + remainingTimeOutMillis - + "ms. for environment creation to complete."); - environmentFuture.get(remainingTimeOutMillis, TimeUnit.MILLISECONDS); - } - else - { - throw te; - } - } - } - 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 replicated environment creation took too long (permitted time " - + setUpTimeOutMillis + "ms)"); - } - } - - private void createEnvironment(File environmentPathFile, EnvironmentConfig envConfig, - final ReplicationConfig replicationConfig) - { - String originalThreadName = Thread.currentThread().getName(); - try - { - _envSetupTimeoutMillis = extractEnvSetupTimeoutMillis(replicationConfig); - _environment = new ReplicatedEnvironment(environmentPathFile, replicationConfig, envConfig); - } - catch (final InsufficientLogException ile) - { - LOGGER.warn("The log files of this node are too old. Network restore will begin now.", ile); - NetworkRestore restore = new NetworkRestore(); - NetworkRestoreConfig config = new NetworkRestoreConfig(); - config.setRetainLogFiles(false); - restore.execute(ile, config); - LOGGER.warn("Network restore complete."); - _environment = new ReplicatedEnvironment(environmentPathFile, replicationConfig, envConfig); - } - finally - { - Thread.currentThread().setName(originalThreadName); - } - - if (LOGGER.isInfoEnabled()) - { - LOGGER.info("Environment is created for node " + _prettyGroupNodeName); - } - } - - private long extractEnvSetupTimeoutMillis(ReplicationConfig replicationConfig) - { - return (long) PropUtil.parseDuration(replicationConfig.getConfigParam(ReplicationConfig.ENV_SETUP_TIMEOUT)); - } - - public int getNumberOfElectableGroupMembers() - { - if (_state.get() != State.OPEN) - { - throw new IllegalStateException("Environment facade is not opened"); - } - return _environment.getGroup().getElectableNodes().size(); - } - - public boolean isMaster() - { - return ReplicatedEnvironment.State.MASTER.name().equals(getNodeState()); - } - - public void setReplicationGroupListener(ReplicationGroupListener replicationGroupListener) - { - if (_replicationGroupListener.compareAndSet(null, replicationGroupListener)) - { - notifyExistingRemoteReplicationNodes(replicationGroupListener); - notifyNodeRolledbackIfNecessary(replicationGroupListener); - } - else - { - throw new IllegalStateException("ReplicationGroupListener is already set on " + _prettyGroupNodeName); - } - } - - /** - * This method should only be invoked from configuration thread on virtual host activation. - * Otherwise, invocation of this method whilst coalescing committer is committing transactions might result in transaction aborts. - */ - public void setMessageStoreDurability(SyncPolicy localTransactionSynchronizationPolicy, SyncPolicy remoteTransactionSynchronizationPolicy, ReplicaAckPolicy replicaAcknowledgmentPolicy) - { - if (_messageStoreDurability == null || localTransactionSynchronizationPolicy != _messageStoreDurability.getLocalSync() - || remoteTransactionSynchronizationPolicy != _messageStoreDurability.getReplicaSync() - || replicaAcknowledgmentPolicy != _messageStoreDurability.getReplicaAck()) - { - _messageStoreDurability = new Durability(localTransactionSynchronizationPolicy, remoteTransactionSynchronizationPolicy, replicaAcknowledgmentPolicy); - - if (_coalescingCommiter != null) - { - _coalescingCommiter.stop(); - _coalescingCommiter = null; - } - - if (localTransactionSynchronizationPolicy == LOCAL_TRANSACTION_SYNCHRONIZATION_POLICY) - { - localTransactionSynchronizationPolicy = SyncPolicy.NO_SYNC; - _coalescingCommiter = new CoalescingCommiter(_configuration.getGroupName(), this); - _coalescingCommiter.start(); - } - _realMessageStoreDurability = new Durability(localTransactionSynchronizationPolicy, remoteTransactionSynchronizationPolicy, replicaAcknowledgmentPolicy); - } - } - - public void setPermittedNodes(Collection<String> permittedNodes) - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug(_prettyGroupNodeName + " permitted nodes set to " + permittedNodes); - } - - _permittedNodes.clear(); - if (permittedNodes != null) - { - _permittedNodes.addAll(permittedNodes); - // We register an app state monitor containing with permitted node list on - // all nodes so that any node can be used as the helper when adding more nodes - // to the group - registerAppStateMonitorIfPermittedNodesSpecified(_permittedNodes); - - ReplicationGroupListener listener = _replicationGroupListener.get(); - int count = 0; - for(ReplicationNode node: _remoteReplicationNodes.values()) - { - if (!isNodePermitted(node)) - { - onIntruder(listener, node); - } - count++; - } - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug(_prettyGroupNodeName + " checked " + count + " node(s)"); - } - } - } - - static NodeState getRemoteNodeState(String groupName, ReplicationNode repNode, int dbPingSocketTimeout) throws IOException, ServiceConnectFailedException - { - if (repNode == null) - { - throw new IllegalArgumentException("Node cannot be null"); - } - return new DbPing(repNode, groupName, dbPingSocketTimeout).getNodeState(); - } - - public static Set<String> convertApplicationStateBytesToPermittedNodeList(byte[] applicationState) - { - if (applicationState == null || applicationState.length == 0) - { - return Collections.emptySet(); - } - - ObjectMapper objectMapper = new ObjectMapper(); - try - { - Map<String, Object> settings = objectMapper.readValue(applicationState, Map.class); - return new HashSet<String>((Collection<String>)settings.get(PERMITTED_NODE_LIST)); - } - catch (Exception e) - { - throw new RuntimeException("Unexpected exception on de-serializing of application state", e); - } - } - - public static Collection<String> connectToHelperNodeAndCheckPermittedHosts(String nodeName, String hostPort, String groupName, String helperNodeName, String helperHostPort, int dbPingSocketTimeout) - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug(String.format("Requesting state of the node '%s' at '%s'", helperNodeName, helperHostPort)); - } - - if (helperNodeName == null || "".equals(helperNodeName)) - { - throw new IllegalConfigurationException(String.format("A helper node is not specified for node '%s'" - + " joining the group '%s'", nodeName, groupName)); - } - - Collection<String> permittedNodes = null; - try - { - ReplicationNodeImpl node = new ReplicationNodeImpl(helperNodeName, helperHostPort); - NodeState state = getRemoteNodeState(groupName, node, dbPingSocketTimeout); - byte[] applicationState = state.getAppState(); - permittedNodes = convertApplicationStateBytesToPermittedNodeList(applicationState); - } - catch (IOException e) - { - throw new IllegalConfigurationException(String.format("Cannot connect to existing node '%s' at '%s'", helperNodeName, helperHostPort), e); - } - catch (ServiceConnectFailedException e) - { - throw new IllegalConfigurationException(String.format("Failure to connect to '%s'", helperHostPort), e); - } - catch (Exception e) - { - throw new RuntimeException(String.format("Cannot retrieve state for node '%s' (%s) from group '%s'", - helperNodeName, helperHostPort, groupName), e); - } - - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug(String.format("Attribute 'permittedNodes' on node '%s' is set to '%s'", helperNodeName, String.valueOf(permittedNodes))); - } - - if (permittedNodes==null || !permittedNodes.contains(hostPort)) - { - throw new IllegalConfigurationException(String.format("Node from '%s' is not permitted!", hostPort)); - } - - return permittedNodes; - } - - private void registerAppStateMonitorIfPermittedNodesSpecified(final Set<String> permittedNodes) - { - if (!permittedNodes.isEmpty()) - { - byte[] data = permittedNodeListToBytes(permittedNodes); - _environment.registerAppStateMonitor(new EnvironmentStateHolder(data)); - } - } - - private boolean isNodePermitted(ReplicationNode replicationNode) - { - if (_permittedNodes.isEmpty()) - { - return true; - } - - String nodeHostPort = getHostPort(replicationNode); - return _permittedNodes.contains(nodeHostPort); - } - - private String getHostPort(ReplicationNode replicationNode) - { - return replicationNode.getHostName() + ":" + replicationNode.getPort(); - } - - - private boolean onIntruder(ReplicationGroupListener replicationGroupListener, ReplicationNode replicationNode) - { - if (replicationGroupListener != null) - { - return replicationGroupListener.onIntruderNode(replicationNode); - } - else - { - LOGGER.warn(String.format( - "Found an intruder node '%s' from ''%s' . The node is not listed in permitted list: %s", - replicationNode.getName(), - getHostPort(replicationNode), - String.valueOf(_permittedNodes))); - return true; - } - } - - private byte[] permittedNodeListToBytes(Set<String> permittedNodeList) - { - HashMap<String, Object> data = new HashMap<String, Object>(); - data.put(PERMITTED_NODE_LIST, permittedNodeList); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectMapper objectMapper = new ObjectMapper(); - try - { - objectMapper.writeValue(baos, data); - } - catch (Exception e) - { - throw new RuntimeException("Unexpected exception on serializing of permitted node list into json", e); - } - return baos.toByteArray(); - } - - private void populateExistingRemoteReplicationNodes() - { - ReplicationGroup group = _environment.getGroup(); - Set<ReplicationNode> nodes = new HashSet<ReplicationNode>(group.getElectableNodes()); - String localNodeName = getNodeName(); - - for (ReplicationNode replicationNode : nodes) - { - String discoveredNodeName = replicationNode.getName(); - if (!discoveredNodeName.equals(localNodeName)) - { - _remoteReplicationNodes.put(replicationNode.getName(), replicationNode); - } - } - } - - private void notifyExistingRemoteReplicationNodes(ReplicationGroupListener listener) - { - for (ReplicationNode value : _remoteReplicationNodes.values()) - { - listener.onReplicationNodeRecovered(value); - } - } - - private void notifyNodeRolledbackIfNecessary(ReplicationGroupListener listener) - { - if (_nodeRolledback) - { - listener.onNodeRolledback(); - _nodeRolledback = false; - } - } - - private void onException(final Exception e) - { - _groupChangeExecutor.submit(new Runnable() - { - @Override - public void run() - { - ReplicationGroupListener listener = _replicationGroupListener.get(); - if (listener != null) - { - listener.onException(e); - } - } - }); - } - - private class RemoteNodeStateLearner implements Callable<Void> - { - private static final long TIMEOUT_WARN_GAP = 1000 * 60 * 5; - private final Map<ReplicationNode, Long> _currentlyTimedOutNodes = new HashMap<>(); - private Map<String, ReplicatedEnvironment.State> _previousGroupState = Collections.emptyMap(); - private boolean _previousDesignatedPrimary; - private int _previousElectableGroupOverride; - - @Override - public Void call() - { - boolean continueMonitoring = true; - try - { - if (_state.get() == State.OPEN) - { - try - { - continueMonitoring = detectGroupChangesAndNotify(); - } - catch(DatabaseException e) - { - handleDatabaseException("Exception on replication group check", e); - } - - if (continueMonitoring) - { - boolean currentDesignatedPrimary = isDesignatedPrimary(); - int currentElectableGroupSizeOverride = getElectableGroupSizeOverride(); - - Map<ReplicationNode, NodeState> nodeStates = discoverNodeStates(_remoteReplicationNodes.values()); - - executeDatabasePingerOnNodeChangesIfMaster(nodeStates, currentDesignatedPrimary, currentElectableGroupSizeOverride); - - notifyGroupListenerAboutNodeStates(nodeStates); - } - } - } - finally - { - State state = _state.get(); - if (state != State.CLOSED && state != State.CLOSING && continueMonitoring) - { - _groupChangeExecutor.schedule(this, _remoteNodeMonitorInterval, TimeUnit.MILLISECONDS); - } - else - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Monitoring task is not scheduled: state " + state + ", continue monitoring flag " + continueMonitoring); - } - } - } - return null; - } - - private boolean detectGroupChangesAndNotify() - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Checking for changes in the group " + _configuration.getGroupName() + " on node " + _configuration.getName()); - } - boolean shouldContinue = true; - String groupName = _configuration.getGroupName(); - ReplicatedEnvironment env = _environment; - ReplicationGroupListener replicationGroupListener = _replicationGroupListener.get(); - if (env != null) - { - ReplicationGroup group = env.getGroup(); - Set<ReplicationNode> nodes = new HashSet<ReplicationNode>(group.getNodes()); - String localNodeName = getNodeName(); - - Map<String, ReplicationNode> removalMap = new HashMap<String, ReplicationNode>(_remoteReplicationNodes); - for (ReplicationNode replicationNode : nodes) - { - String discoveredNodeName = replicationNode.getName(); - if (!discoveredNodeName.equals(localNodeName)) - { - if (!_remoteReplicationNodes.containsKey(discoveredNodeName)) - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Remote replication node added '" + replicationNode + "' to '" + groupName + "'"); - } - - _remoteReplicationNodes.put(discoveredNodeName, replicationNode); - - if (isNodePermitted(replicationNode)) - { - if (replicationGroupListener != null) - { - replicationGroupListener.onReplicationNodeAddedToGroup(replicationNode); - } - } - else - { - if (!onIntruder(replicationGroupListener, replicationNode)) - { - shouldContinue = false; - } - } - } - else - { - removalMap.remove(discoveredNodeName); - } - } - } - - if (!removalMap.isEmpty()) - { - for (Map.Entry<String, ReplicationNode> replicationNodeEntry : removalMap.entrySet()) - { - String replicationNodeName = replicationNodeEntry.getKey(); - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Remote replication node removed '" + replicationNodeName + "' from '" + groupName + "'"); - } - _remoteReplicationNodes.remove(replicationNodeName); - if (replicationGroupListener != null) - { - replicationGroupListener.onReplicationNodeRemovedFromGroup(replicationNodeEntry.getValue()); - } - } - } - } - return shouldContinue; - } - - private Map<ReplicationNode, NodeState> discoverNodeStates(Collection<ReplicationNode> electableNodes) - { - final Map<ReplicationNode, NodeState> nodeStates = new HashMap<ReplicationNode, NodeState>(); - Map<ReplicationNode, Future<Void>> futureMap = new HashMap<ReplicationNode, Future<Void>>(); - - for (final ReplicationNode node : electableNodes) - { - nodeStates.put(node, null); - - Future<Void> future = _groupChangeExecutor.submit(new Callable<Void>() - { - @Override - public Void call() - { - NodeState nodeStateObject = null; - try - { - nodeStateObject = getRemoteNodeState(_configuration.getGroupName(), node, _dbPingSocketTimeout); - } - catch (IOException | ServiceConnectFailedException | com.sleepycat.je.rep.utilint.BinaryProtocol.ProtocolException e ) - { - // Cannot discover node states. The node state should be treated as UNKNOWN - } - - nodeStates.put(node, nodeStateObject); - return null; - } - }); - futureMap.put(node, future); - } - - boolean atLeastOneNodeTimesOut = false; - - for (Map.Entry<ReplicationNode, Future<Void>> entry : futureMap.entrySet()) - { - ReplicationNode node = entry.getKey(); - String nodeName = node.getName(); - Future<Void> future = entry.getValue(); - try - { - future.get(_remoteNodeMonitorInterval, TimeUnit.MILLISECONDS); - if (_currentlyTimedOutNodes.remove(node) != null) - { - LOGGER.warn("Node '" + nodeName + "' from group " + _configuration.getGroupName() - + " is responding again."); - } - } - catch (InterruptedException e) - { - Thread.currentThread().interrupt(); - } - catch (ExecutionException e) - { - LOGGER.warn("Cannot determine state for node '" + nodeName + "' from group " - + _configuration.getGroupName(), e.getCause()); - } - catch (TimeoutException e) - { - atLeastOneNodeTimesOut = true; - if (! _currentlyTimedOutNodes.containsKey(node)) - { - LOGGER.warn("Timeout whilst determining state for node '" + nodeName + "' from group " - + _configuration.getGroupName()); - _currentlyTimedOutNodes.put(node, System.currentTimeMillis()); - } - else if (_currentlyTimedOutNodes.get(node) > (System.currentTimeMillis() + TIMEOUT_WARN_GAP)) - { - LOGGER.warn("Node '" + nodeName + "' from group " - + _configuration.getGroupName() - + " is still timing out."); - _currentlyTimedOutNodes.put(node, System.currentTimeMillis()); - } - - future.cancel(true); - } - } - - if (!atLeastOneNodeTimesOut) - { - _currentlyTimedOutNodes.clear(); - } - return nodeStates; - } - - /** - * If the state of the group changes or the user alters the parameters used to determine if the - * there is quorum in the group, execute a single small transaction to discover is quorum is - * still available. This allows us to discover if quorum is lost in a timely manner, rather than - * having to await the next user transaction. - */ - private void executeDatabasePingerOnNodeChangesIfMaster(final Map<ReplicationNode, NodeState> nodeStates, - final boolean currentDesignatedPrimary, - final int currentElectableGroupSizeOverride) - { - if (ReplicatedEnvironment.State.MASTER == _environment.getState()) - { - Map<String, ReplicatedEnvironment.State> currentGroupState = new HashMap<>(); - for (Map.Entry<ReplicationNode, NodeState> entry : nodeStates.entrySet()) - { - ReplicationNode node = entry.getKey(); - NodeState nodeState = entry.getValue(); - ReplicatedEnvironment.State state = nodeState == null? ReplicatedEnvironment.State.UNKNOWN : nodeState.getNodeState(); - currentGroupState.put(node.getName(), state); - } - - ReplicatedEnvironmentFacade.this.isDesignatedPrimary(); - ReplicatedEnvironmentFacade.this.getElectableGroupSizeOverride(); - - boolean stateChanged = !_previousGroupState.equals(currentGroupState) - || currentDesignatedPrimary != _previousDesignatedPrimary - || currentElectableGroupSizeOverride != _previousElectableGroupOverride; - - _previousGroupState = currentGroupState; - _previousDesignatedPrimary = currentDesignatedPrimary; - _previousElectableGroupOverride = currentElectableGroupSizeOverride; - - if (stateChanged && State.OPEN == _state.get()) - { - new DatabasePinger().pingDb(ReplicatedEnvironmentFacade.this); - } - } - } - - private void notifyGroupListenerAboutNodeStates(final Map<ReplicationNode, NodeState> nodeStates) - { - ReplicationGroupListener replicationGroupListener = _replicationGroupListener.get(); - if (replicationGroupListener != null) - { - for (Map.Entry<ReplicationNode, NodeState> entry : nodeStates.entrySet()) - { - replicationGroupListener.onNodeState(entry.getKey(), entry.getValue()); - } - } - } - } - - public static enum State - { - OPENING, - OPEN, - RESTARTING, - CLOSING, - CLOSED - } - - private static class EnvironmentStateHolder implements AppStateMonitor - { - private byte[] _data; - - private EnvironmentStateHolder(byte[] data) - { - this._data = data; - } - - @Override - public byte[] getAppState() - { - return _data; - } - } - - public static class ReplicationNodeImpl implements ReplicationNode - { - - private final InetSocketAddress _address; - private final String _nodeName; - private final String _host; - private final int _port; - - public ReplicationNodeImpl(String nodeName, String hostPort) - { - String[] tokens = hostPort.split(":"); - if (tokens.length != 2) - { - throw new IllegalArgumentException("Unexpected host port value :" + hostPort); - } - _host = tokens[0]; - _port = Integer.parseInt(tokens[1]); - _nodeName = nodeName; - _address = new InetSocketAddress(_host, _port); - } - - @Override - public String getName() - { - return _nodeName; - } - - @Override - public NodeType getType() - { - return NodeType.ELECTABLE; - } - - @Override - public InetSocketAddress getSocketAddress() - { - return _address; - } - - @Override - public String getHostName() - { - return _host; - } - - @Override - public int getPort() - { - return _port; - } - - @Override - public String toString() - { - return "ReplicationNodeImpl{" + - "_nodeName='" + _nodeName + '\'' + - ", _host='" + _host + '\'' + - ", _port=" + _port + - '}'; - } - } - - private class ExceptionListener implements com.sleepycat.je.ExceptionListener - { - @Override - public void exceptionThrown(final ExceptionEvent event) - { - Exception exception = event.getException(); - - if (exception instanceof LogWriteException) - { - onException(exception); - } - - if (exception instanceof RollbackException) - { - // Usually caused use of weak durability options: node priority zero, - // designated primary, electable group override. - RollbackException re = (RollbackException) exception; - - LOGGER.warn(_prettyGroupNodeName + " has transaction(s) ahead of the current master. These" - + " must be discarded to allow this node to rejoin the group." - + " This condition is normally caused by the use of weak durability options."); - _nodeRolledback = true; - tryToRestartEnvironment(re); - } - else - { - LOGGER.error("Asynchronous exception thrown by BDB thread '" + event.getThreadName() + "'", event.getException()); - } - } - } -} 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 deleted file mode 100644 index 09d681608f..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacadeFactory.java +++ /dev/null @@ -1,156 +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.replication; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Pattern; - -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.store.berkeleydb.EnvironmentFacade; -import org.apache.qpid.server.store.berkeleydb.EnvironmentFacadeFactory; -import org.apache.qpid.server.store.berkeleydb.HASettings; - -public class ReplicatedEnvironmentFacadeFactory implements EnvironmentFacadeFactory -{ - public static final Pattern NON_REP_JE_PARAM_PATTERN = Pattern.compile("^je\\.(?!rep\\.).*"); - public static final Pattern REP_JE_PARAM_PATTERN = Pattern.compile("^je\\.rep\\..*"); - - @Override - public EnvironmentFacade createEnvironmentFacade(final ConfiguredObject<?> parent) - { - final HASettings settings = (HASettings) parent; - - ReplicatedEnvironmentConfiguration configuration = new ReplicatedEnvironmentConfiguration() - { - @Override - public boolean isDesignatedPrimary() - { - return settings.isDesignatedPrimary(); - } - - @Override - public String getStorePath() - { - return settings.getStorePath(); - } - - @Override - public Map<String, String> getParameters() - { - return buildEnvironmentConfigParameters(parent); - } - - @Override - public Map<String, String> getReplicationParameters() - { - return buildReplicationConfigParameters(parent); - } - - @Override - public String getHelperNodeName() - { - return settings.getHelperNodeName(); - } - - @Override - public int getQuorumOverride() - { - return settings.getQuorumOverride(); - } - - @Override - public int getPriority() - { - return settings.getPriority(); - } - - @Override - public String getName() - { - return parent.getName(); - } - - @Override - public String getHostPort() - { - return settings.getAddress(); - } - - @Override - public String getHelperHostPort() - { - return settings.getHelperAddress(); - } - - @Override - public String getGroupName() - { - return settings.getGroupName(); - } - - @Override - public int getFacadeParameter(final String parameterName, final int defaultValue) - { - if (parent.getContextKeys(false).contains(parameterName)) - { - return parent.getContextValue(Integer.class, parameterName); - } - else - { - return defaultValue; - } - } - - }; - return new ReplicatedEnvironmentFacade(configuration); - - } - - private Map<String, String> buildEnvironmentConfigParameters(ConfiguredObject<?> parent) - { - return buildConfig(parent, NON_REP_JE_PARAM_PATTERN); - } - - private Map<String, String> buildReplicationConfigParameters(ConfiguredObject<?> parent) - { - - return buildConfig(parent, REP_JE_PARAM_PATTERN); - } - - private Map<String, String> buildConfig(ConfiguredObject<?> parent, Pattern paramName) - { - Map<String, String> targetMap = new HashMap<>(); - for (String name : parent.getContextKeys(false)) - { - if (paramName.matcher(name).matches()) - { - String contextValue = parent.getContextValue(String.class,name); - targetMap.put(name, contextValue); - } - } - - return Collections.unmodifiableMap(targetMap); - } - - -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicationGroupListener.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicationGroupListener.java deleted file mode 100644 index 888be3adff..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicationGroupListener.java +++ /dev/null @@ -1,69 +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.replication; - -import com.sleepycat.je.rep.NodeState; -import com.sleepycat.je.rep.ReplicationNode; - -public interface ReplicationGroupListener -{ - /** - * Fired when a remote replication node is added to a group. This event happens - * exactly once just after a new replication node is created. - */ - void onReplicationNodeAddedToGroup(ReplicationNode node); - - /** - * Fired exactly once for each existing remote node. Used to inform the application - * on any existing nodes as it starts up for the first time. - */ - void onReplicationNodeRecovered(ReplicationNode node); - - /** - * Fired when a remote replication node is (permanently) removed from group. This event - * happens exactly once just after the existing replication node is deleted. - */ - void onReplicationNodeRemovedFromGroup(ReplicationNode node); - - /** - * Invoked to notify listener on node state update - */ - void onNodeState(ReplicationNode node, NodeState nodeState); - - /** - * Invoked on intruder node detected - */ - boolean onIntruderNode(ReplicationNode node); - - void onNoMajority(); - - /** - * Signifies that node need to discard one or more transactions in order to rejoin the group. Most likely - * caused by use of the weak durability options such as node priority zero. - */ - void onNodeRolledback(); - - /** - * Callback method to invoke on critical JE exceptions - * @param e je exception - */ - void onException(Exception e); -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBinding.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBinding.java deleted file mode 100644 index 38a2215fe7..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBinding.java +++ /dev/null @@ -1,128 +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.tuple; - -import java.io.IOException; -import java.io.StringWriter; -import java.util.Map; -import java.util.UUID; - -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.store.ConfiguredObjectRecord; - -import com.sleepycat.bind.tuple.TupleBinding; -import com.sleepycat.bind.tuple.TupleInput; -import com.sleepycat.bind.tuple.TupleOutput; -import org.apache.qpid.server.store.StoreException; -import org.apache.qpid.server.store.berkeleydb.BDBConfiguredObjectRecord; -import org.codehaus.jackson.JsonGenerationException; -import org.codehaus.jackson.JsonGenerator; -import org.codehaus.jackson.JsonProcessingException; -import org.codehaus.jackson.Version; -import org.codehaus.jackson.map.JsonMappingException; -import org.codehaus.jackson.map.JsonSerializer; -import org.codehaus.jackson.map.Module; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.map.SerializerProvider; -import org.codehaus.jackson.map.module.SimpleModule; - -public class ConfiguredObjectBinding extends TupleBinding<ConfiguredObjectRecord> -{ - private static final ConfiguredObjectBinding INSTANCE = new ConfiguredObjectBinding(null); - - private final UUID _uuid; - - private static final Module _module; - static - { - SimpleModule module= new SimpleModule("ConfiguredObjectSerializer", new Version(1,0,0,null)); - - final JsonSerializer<ConfiguredObject> serializer = new JsonSerializer<ConfiguredObject>() - { - @Override - public void serialize(final ConfiguredObject value, - final JsonGenerator jgen, - final SerializerProvider provider) - throws IOException, JsonProcessingException - { - jgen.writeString(value.getId().toString()); - } - }; - module.addSerializer(ConfiguredObject.class, serializer); - - _module = module; - } - - public static ConfiguredObjectBinding getInstance() - { - return INSTANCE; - } - - public ConfiguredObjectBinding(UUID uuid) - { - _uuid = uuid; - } - - public BDBConfiguredObjectRecord entryToObject(TupleInput tupleInput) - { - String type = tupleInput.readString(); - String json = tupleInput.readString(); - ObjectMapper mapper = new ObjectMapper(); - try - { - Map<String,Object> value = mapper.readValue(json, Map.class); - BDBConfiguredObjectRecord configuredObject = new BDBConfiguredObjectRecord(_uuid, type, value); - return configuredObject; - } - catch (IOException e) - { - //should never happen - throw new StoreException(e); - } - - } - - public void objectToEntry(ConfiguredObjectRecord object, TupleOutput tupleOutput) - { - try - { - StringWriter writer = new StringWriter(); - final ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.registerModule(_module); - objectMapper.writeValue(writer, object.getAttributes()); - tupleOutput.writeString(object.getType()); - tupleOutput.writeString(writer.toString()); - } - catch (JsonMappingException e) - { - throw new StoreException(e); - } - catch (JsonGenerationException e) - { - throw new StoreException(e); - } - catch (IOException e) - { - throw new StoreException(e); - } - } - -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/ContentBinding.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/ContentBinding.java deleted file mode 100644 index 9154ca114a..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/ContentBinding.java +++ /dev/null @@ -1,52 +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.tuple; - -import com.sleepycat.bind.tuple.TupleBinding; -import com.sleepycat.bind.tuple.TupleInput; -import com.sleepycat.bind.tuple.TupleOutput; - -public class ContentBinding extends TupleBinding<byte[]> -{ - private static final ContentBinding INSTANCE = new ContentBinding(); - - public static ContentBinding getInstance() - { - return INSTANCE; - } - - /** private constructor forces getInstance instead */ - private ContentBinding() { } - - @Override - public byte[] entryToObject(final TupleInput input) - { - byte[] data = new byte[input.available()]; - input.read(data); - return data; - } - - @Override - public void objectToEntry(final byte[] data, final TupleOutput output) - { - output.write(data); - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/HierarchyKeyBinding.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/HierarchyKeyBinding.java deleted file mode 100644 index 13adaabfc8..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/HierarchyKeyBinding.java +++ /dev/null @@ -1,59 +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.tuple; - -import com.sleepycat.bind.tuple.TupleBinding; -import com.sleepycat.bind.tuple.TupleInput; -import com.sleepycat.bind.tuple.TupleOutput; -import org.apache.qpid.server.store.berkeleydb.entry.HierarchyKey; -import org.apache.qpid.server.store.berkeleydb.entry.QueueEntryKey; - -import java.util.UUID; - -public class HierarchyKeyBinding extends TupleBinding<HierarchyKey> -{ - - private static final HierarchyKeyBinding INSTANCE = new HierarchyKeyBinding(); - - public static HierarchyKeyBinding getInstance() - { - return INSTANCE; - } - - /** private constructor forces getInstance instead */ - private HierarchyKeyBinding() { } - - public HierarchyKey entryToObject(TupleInput tupleInput) - { - UUID childId = new UUID(tupleInput.readLong(), tupleInput.readLong()); - String parentType = tupleInput.readString(); - - return new HierarchyKey(childId, parentType); - } - - public void objectToEntry(HierarchyKey hk, TupleOutput tupleOutput) - { - UUID uuid = hk.getChildId(); - tupleOutput.writeLong(uuid.getMostSignificantBits()); - tupleOutput.writeLong(uuid.getLeastSignificantBits()); - tupleOutput.writeString(hk.getParentType()); - } -}
\ No newline at end of file diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/MessageMetaDataBinding.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/MessageMetaDataBinding.java deleted file mode 100644 index e0a79fa1c1..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/MessageMetaDataBinding.java +++ /dev/null @@ -1,76 +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.tuple; - -import java.nio.ByteBuffer; - -import com.sleepycat.bind.tuple.TupleBinding; -import com.sleepycat.bind.tuple.TupleInput; -import com.sleepycat.bind.tuple.TupleOutput; - -import org.apache.qpid.server.plugin.MessageMetaDataType; -import org.apache.qpid.server.store.MessageMetaDataTypeRegistry; -import org.apache.qpid.server.store.StorableMessageMetaData; - -/** - * Handles the mapping to and from message meta data - */ -public class MessageMetaDataBinding extends TupleBinding<StorableMessageMetaData> -{ - private static final MessageMetaDataBinding INSTANCE = new MessageMetaDataBinding(); - - public static MessageMetaDataBinding getInstance() - { - return INSTANCE; - } - - /** private constructor forces getInstance instead */ - private MessageMetaDataBinding() { } - - @Override - public StorableMessageMetaData entryToObject(TupleInput tupleInput) - { - final int bodySize = tupleInput.readInt(); - byte[] dataAsBytes = new byte[bodySize]; - tupleInput.readFast(dataAsBytes); - - ByteBuffer buf = ByteBuffer.wrap(dataAsBytes); - buf.position(1); - buf = buf.slice(); - MessageMetaDataType type = MessageMetaDataTypeRegistry.fromOrdinal(dataAsBytes[0]); - return type.createMetaData(buf); - } - - @Override - public void objectToEntry(StorableMessageMetaData metaData, TupleOutput tupleOutput) - { - final int bodySize = 1 + metaData.getStorableSize(); - byte[] underlying = new byte[bodySize]; - underlying[0] = (byte) metaData.getType().ordinal(); - ByteBuffer buf = ByteBuffer.wrap(underlying); - buf.position(1); - buf = buf.slice(); - - metaData.writeToBuffer(buf); - tupleOutput.writeInt(bodySize); - tupleOutput.writeFast(underlying); - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/PreparedTransactionBinding.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/PreparedTransactionBinding.java deleted file mode 100644 index 4d111e5c4f..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/PreparedTransactionBinding.java +++ /dev/null @@ -1,189 +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.tuple; - -import java.util.UUID; - -import com.sleepycat.bind.tuple.TupleBinding; -import com.sleepycat.bind.tuple.TupleInput; -import com.sleepycat.bind.tuple.TupleOutput; -import org.apache.qpid.server.message.EnqueueableMessage; -import org.apache.qpid.server.store.MessageDurability; -import org.apache.qpid.server.store.MessageEnqueueRecord; -import org.apache.qpid.server.store.StoredMessage; -import org.apache.qpid.server.store.Transaction; -import org.apache.qpid.server.store.TransactionLogResource; -import org.apache.qpid.server.store.berkeleydb.AbstractBDBMessageStore; -import org.apache.qpid.server.store.berkeleydb.entry.PreparedTransaction; - -public class PreparedTransactionBinding extends TupleBinding<PreparedTransaction> -{ - @Override - public PreparedTransaction entryToObject(TupleInput input) - { - Transaction.EnqueueRecord[] enqueues = readEnqueueRecords(input); - - Transaction.DequeueRecord[] dequeues = readDequeueRecords(input); - - return new PreparedTransaction(enqueues, dequeues); - } - - private Transaction.EnqueueRecord[] readEnqueueRecords(TupleInput input) - { - Transaction.EnqueueRecord[] records = new Transaction.EnqueueRecord[input.readInt()]; - for(int i = 0; i < records.length; i++) - { - records[i] = new EnqueueRecordImpl(new UUID(input.readLong(), input.readLong()), input.readLong()); - } - return records; - } - - private Transaction.DequeueRecord[] readDequeueRecords(TupleInput input) - { - Transaction.DequeueRecord[] records = new Transaction.DequeueRecord[input.readInt()]; - for(int i = 0; i < records.length; i++) - { - records[i] = new DequeueRecordImpl(new UUID(input.readLong(), input.readLong()), input.readLong()); - } - return records; - } - - - @Override - public void objectToEntry(PreparedTransaction preparedTransaction, TupleOutput output) - { - writeRecords(preparedTransaction.getEnqueues(), output); - writeRecords(preparedTransaction.getDequeues(), output); - - } - - private void writeRecords(Transaction.EnqueueRecord[] records, TupleOutput output) - { - if(records == null) - { - output.writeInt(0); - } - else - { - output.writeInt(records.length); - for(Transaction.EnqueueRecord record : records) - { - UUID id = record.getResource().getId(); - output.writeLong(id.getMostSignificantBits()); - output.writeLong(id.getLeastSignificantBits()); - output.writeLong(record.getMessage().getMessageNumber()); - } - } - } - - private void writeRecords(Transaction.DequeueRecord[] records, TupleOutput output) - { - if(records == null) - { - output.writeInt(0); - } - else - { - output.writeInt(records.length); - for(Transaction.DequeueRecord record : records) - { - UUID id = record.getEnqueueRecord().getQueueId(); - output.writeLong(id.getMostSignificantBits()); - output.writeLong(id.getLeastSignificantBits()); - output.writeLong(record.getEnqueueRecord().getMessageNumber()); - } - } - } - - private static class EnqueueRecordImpl implements Transaction.EnqueueRecord, TransactionLogResource, EnqueueableMessage - { - - private long _messageNumber; - private UUID _queueId; - - public EnqueueRecordImpl(UUID queueId, long messageNumber) - { - _messageNumber = messageNumber; - _queueId = queueId; - } - - public TransactionLogResource getResource() - { - return this; - } - - public EnqueueableMessage getMessage() - { - return this; - } - - public long getMessageNumber() - { - return _messageNumber; - } - - public boolean isPersistent() - { - return true; - } - - public StoredMessage<?> getStoredMessage() - { - throw new UnsupportedOperationException(); - } - - @Override - public String getName() - { - return _queueId.toString(); - } - - @Override - public UUID getId() - { - return _queueId; - } - - @Override - public MessageDurability getMessageDurability() - { - return MessageDurability.DEFAULT; - } - } - - private static class DequeueRecordImpl implements Transaction.DequeueRecord - { - - private final AbstractBDBMessageStore.BDBEnqueueRecord _record; - - public DequeueRecordImpl(final UUID queueId, final long messageNumber) - { - _record = new AbstractBDBMessageStore.BDBEnqueueRecord(queueId, messageNumber); - } - - @Override - public MessageEnqueueRecord getEnqueueRecord() - { - return _record; - } - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/QueueEntryBinding.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/QueueEntryBinding.java deleted file mode 100644 index 22d0ede31f..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/QueueEntryBinding.java +++ /dev/null @@ -1,59 +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.tuple; - -import java.util.UUID; - -import com.sleepycat.bind.tuple.TupleBinding; -import com.sleepycat.bind.tuple.TupleInput; -import com.sleepycat.bind.tuple.TupleOutput; - -import org.apache.qpid.server.store.berkeleydb.entry.QueueEntryKey; - -public class QueueEntryBinding extends TupleBinding<QueueEntryKey> -{ - - private static final QueueEntryBinding INSTANCE = new QueueEntryBinding(); - - public static QueueEntryBinding getInstance() - { - return INSTANCE; - } - - /** private constructor forces getInstance instead */ - private QueueEntryBinding() { } - - public QueueEntryKey entryToObject(TupleInput tupleInput) - { - UUID queueId = new UUID(tupleInput.readLong(), tupleInput.readLong()); - long messageId = tupleInput.readLong(); - - return new QueueEntryKey(queueId, messageId); - } - - public void objectToEntry(QueueEntryKey mk, TupleOutput tupleOutput) - { - UUID uuid = mk.getQueueId(); - tupleOutput.writeLong(uuid.getMostSignificantBits()); - tupleOutput.writeLong(uuid.getLeastSignificantBits()); - tupleOutput.writeLong(mk.getMessageId()); - } -}
\ No newline at end of file diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/StringMapBinding.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/StringMapBinding.java deleted file mode 100644 index 15f31953f4..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/StringMapBinding.java +++ /dev/null @@ -1,59 +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.tuple; - -import com.sleepycat.bind.tuple.TupleBinding; -import com.sleepycat.bind.tuple.TupleInput; -import com.sleepycat.bind.tuple.TupleOutput; - -import java.util.HashMap; -import java.util.Map; - -public class StringMapBinding extends TupleBinding<Map<String,String>> -{ - private static final StringMapBinding INSTANCE = new StringMapBinding(); - - public Map<String, String> entryToObject(final TupleInput tupleInput) - { - int entries = tupleInput.readInt(); - Map<String,String> map = new HashMap<String,String>(entries); - for(int i = 0; i < entries; i++) - { - map.put(tupleInput.readString(), tupleInput.readString()); - } - return map; - } - - public void objectToEntry(final Map<String, String> stringStringMap, final TupleOutput tupleOutput) - { - tupleOutput.writeInt(stringStringMap.size()); - for(Map.Entry<String,String> entry : stringStringMap.entrySet()) - { - tupleOutput.writeString(entry.getKey()); - tupleOutput.writeString(entry.getValue()); - } - } - - public static StringMapBinding getInstance() - { - return INSTANCE; - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/UUIDTupleBinding.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/UUIDTupleBinding.java deleted file mode 100644 index f8657cdd49..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/UUIDTupleBinding.java +++ /dev/null @@ -1,48 +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.tuple; - -import com.sleepycat.bind.tuple.TupleBinding; -import com.sleepycat.bind.tuple.TupleInput; -import com.sleepycat.bind.tuple.TupleOutput; - -import java.util.UUID; - -public class UUIDTupleBinding extends TupleBinding<UUID> -{ - private static final UUIDTupleBinding INSTANCE = new UUIDTupleBinding(); - - public UUID entryToObject(final TupleInput tupleInput) - { - return new UUID(tupleInput.readLong(), tupleInput.readLong()); - } - - public void objectToEntry(final UUID uuid, final TupleOutput tupleOutput) - { - tupleOutput.writeLong(uuid.getMostSignificantBits()); - tupleOutput.writeLong(uuid.getLeastSignificantBits()); - } - - public static UUIDTupleBinding getInstance() - { - return INSTANCE; - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/XidBinding.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/XidBinding.java deleted file mode 100644 index 5918e5ab54..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/XidBinding.java +++ /dev/null @@ -1,70 +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.tuple; - -import com.sleepycat.bind.tuple.TupleBinding; -import com.sleepycat.bind.tuple.TupleInput; -import com.sleepycat.bind.tuple.TupleOutput; - -import org.apache.qpid.server.store.Xid; - -public class XidBinding extends TupleBinding<Xid> -{ - - private static final XidBinding INSTANCE = new XidBinding(); - - public static XidBinding getInstance() - { - return INSTANCE; - } - - /** private constructor forces getInstance instead */ - private XidBinding() { } - - @Override - public Xid entryToObject(TupleInput input) - { - long format = input.readLong(); - byte[] globalId = new byte[input.readInt()]; - input.readFast(globalId); - byte[] branchId = new byte[input.readInt()]; - input.readFast(branchId); - return new Xid(format,globalId,branchId); - } - - @Override - public void objectToEntry(Xid xid, TupleOutput output) - { - output.writeLong(xid.getFormat()); - output.writeInt(xid.getGlobalId() == null ? 0 : xid.getGlobalId().length); - if(xid.getGlobalId() != null) - { - output.write(xid.getGlobalId()); - } - output.writeInt(xid.getBranchId() == null ? 0 : xid.getBranchId().length); - if(xid.getBranchId() != null) - { - output.write(xid.getBranchId()); - } - - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractStoreUpgrade.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractStoreUpgrade.java deleted file mode 100644 index 4a53a00363..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractStoreUpgrade.java +++ /dev/null @@ -1,77 +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.upgrade; - -import java.util.List; - -import com.sleepycat.je.Database; -import com.sleepycat.je.Environment; -import com.sleepycat.je.Transaction; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public abstract class AbstractStoreUpgrade implements StoreUpgrade -{ - private static final Logger _logger = LoggerFactory.getLogger(AbstractStoreUpgrade.class); - - protected void reportFinished(Environment environment, int version) - { - _logger.info("Completed upgrade to version " + version); - if (_logger.isDebugEnabled()) - { - _logger.debug("Upgraded:"); - reportDatabaseRowCount(environment); - } - } - - private void reportDatabaseRowCount(Environment environment) - { - List<String> databases = environment.getDatabaseNames(); - for (String database : databases) - { - _logger.debug(" " + getRowCount(database, environment) + " rows in " + database); - } - } - - protected void reportStarting(Environment environment, int version) - { - _logger.info("Starting store upgrade from version " + version); - if (_logger.isDebugEnabled()) - { - _logger.debug("Upgrading:"); - reportDatabaseRowCount(environment); - } - } - - private long getRowCount(String databaseName, Environment environment) - { - DatabaseCallable<Long> operation = new DatabaseCallable<Long>() - { - @Override - public Long call(Database sourceDatabase, Database targetDatabase, Transaction transaction) - { - return sourceDatabase.count(); - } - }; - return new DatabaseTemplate(environment, databaseName, null).call(operation); - } - -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/CursorOperation.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/CursorOperation.java deleted file mode 100644 index 59573ee680..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/CursorOperation.java +++ /dev/null @@ -1,90 +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.upgrade; - - -import com.sleepycat.je.Database; -import com.sleepycat.je.DatabaseEntry; -import com.sleepycat.je.Transaction; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public abstract class CursorOperation implements DatabaseRunnable -{ - private static final Logger _logger = LoggerFactory.getLogger(CursorOperation.class); - - private CursorTemplate _template; - private long _rowCount; - private long _processedRowCount; - - @Override - public void run(final Database sourceDatabase, final Database targetDatabase, final Transaction transaction) - { - _rowCount = sourceDatabase.count(); - _template = new CursorTemplate(sourceDatabase, transaction, new DatabaseEntryCallback() - { - @Override - public void processEntry(final Database database, final Transaction transaction, final DatabaseEntry key, - final DatabaseEntry value) - { - _processedRowCount++; - CursorOperation.this.processEntry(database, targetDatabase, transaction, key, value); - if (getProcessedCount() % 1000 == 0) - { - _logger.info("Processed " + getProcessedCount() + " records of " + getRowCount() + "."); - } - } - - }); - _template.processEntries(); - } - - public void abort() - { - if (_template != null) - { - _template.abort(); - } - } - - public boolean deleteCurrent() - { - if (_template != null) - { - return _template.deleteCurrent(); - } - return false; - } - - public long getRowCount() - { - return _rowCount; - } - - public long getProcessedCount() - { - return _processedRowCount; - } - - public abstract void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, - DatabaseEntry key, DatabaseEntry value); - -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/CursorTemplate.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/CursorTemplate.java deleted file mode 100644 index dc68837d47..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/CursorTemplate.java +++ /dev/null @@ -1,75 +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.upgrade; - -import com.sleepycat.je.Cursor; -import com.sleepycat.je.CursorConfig; -import com.sleepycat.je.Database; -import com.sleepycat.je.DatabaseEntry; -import com.sleepycat.je.LockMode; -import com.sleepycat.je.OperationStatus; -import com.sleepycat.je.Transaction; - -public class CursorTemplate -{ - private Database _database; - private Transaction _transaction; - private DatabaseEntryCallback _databaseEntryCallback; - private Cursor _cursor; - private boolean _iterating; - - public CursorTemplate(Database database, Transaction transaction, DatabaseEntryCallback databaseEntryCallback) - { - _database = database; - _transaction = transaction; - _databaseEntryCallback = databaseEntryCallback; - } - - public void processEntries() - { - _cursor = _database.openCursor(_transaction, CursorConfig.READ_COMMITTED); - DatabaseEntry key = new DatabaseEntry(); - DatabaseEntry value = new DatabaseEntry(); - - try - { - _iterating = true; - while (_iterating && _cursor.getNext(key, value, LockMode.DEFAULT) == OperationStatus.SUCCESS) - { - _databaseEntryCallback.processEntry(_database, _transaction, key, value); - } - } - finally - { - _cursor.close(); - } - } - - public boolean deleteCurrent() - { - return _cursor.delete() == OperationStatus.SUCCESS; - } - - public void abort() - { - _iterating = false; - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/DatabaseCallable.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/DatabaseCallable.java deleted file mode 100644 index bf5462ef48..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/DatabaseCallable.java +++ /dev/null @@ -1,29 +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.upgrade; - -import com.sleepycat.je.Database; -import com.sleepycat.je.Transaction; - -public interface DatabaseCallable<T> -{ - public T call(Database sourceDatabase, Database targetDatabase, Transaction transaction); -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/DatabaseEntryCallback.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/DatabaseEntryCallback.java deleted file mode 100644 index 8ac22e5dfb..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/DatabaseEntryCallback.java +++ /dev/null @@ -1,30 +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.upgrade; - -import com.sleepycat.je.Database; -import com.sleepycat.je.DatabaseEntry; -import com.sleepycat.je.Transaction; - -public interface DatabaseEntryCallback -{ - void processEntry(Database database, Transaction transaction, DatabaseEntry key, DatabaseEntry value); -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/DatabaseRunnable.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/DatabaseRunnable.java deleted file mode 100644 index 3e9e6a3497..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/DatabaseRunnable.java +++ /dev/null @@ -1,30 +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.upgrade; - -import com.sleepycat.je.Database; -import com.sleepycat.je.Transaction; - -public interface DatabaseRunnable -{ - public void run(Database sourceDatabase, Database targetDatabase, Transaction transaction); - -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/DatabaseTemplate.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/DatabaseTemplate.java deleted file mode 100644 index 464f4b4101..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/DatabaseTemplate.java +++ /dev/null @@ -1,114 +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.upgrade; - -import com.sleepycat.je.Database; -import com.sleepycat.je.DatabaseConfig; -import com.sleepycat.je.Environment; -import com.sleepycat.je.Transaction; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class DatabaseTemplate -{ - private static final Logger _logger = LoggerFactory.getLogger(DatabaseTemplate.class); - - private Environment _environment; - private String _sourceDatabaseName; - private String _targetDatabaseName; - private Transaction _parentTransaction; - - public DatabaseTemplate(Environment environment, String sourceDatabaseName, Transaction transaction) - { - this(environment, sourceDatabaseName, null, transaction); - } - - public DatabaseTemplate(Environment environment, String sourceDatabaseName, String targetDatabaseName, - Transaction parentTransaction) - { - _environment = environment; - _sourceDatabaseName = sourceDatabaseName; - _targetDatabaseName = targetDatabaseName; - _parentTransaction = parentTransaction; - } - - public void run(DatabaseRunnable databaseRunnable) - { - DatabaseCallable<Void> callable = runnableToCallable(databaseRunnable); - call(callable); - } - - public <T> T call(DatabaseCallable<T> databaseCallable) - { - Database sourceDatabase = null; - Database targetDatabase = null; - try - { - DatabaseConfig dbConfig = new DatabaseConfig(); - dbConfig.setTransactional(true); - dbConfig.setAllowCreate(true); - - sourceDatabase = _environment.openDatabase(_parentTransaction, _sourceDatabaseName, dbConfig); - - if (_targetDatabaseName != null) - { - targetDatabase = _environment.openDatabase(_parentTransaction, _targetDatabaseName, dbConfig); - } - - return databaseCallable.call(sourceDatabase, targetDatabase, _parentTransaction); - } - finally - { - closeDatabase(sourceDatabase); - closeDatabase(targetDatabase); - } - } - - private DatabaseCallable<Void> runnableToCallable(final DatabaseRunnable databaseRunnable) - { - return new DatabaseCallable<Void>() - { - - @Override - public Void call(Database sourceDatabase, Database targetDatabase, Transaction transaction) - { - databaseRunnable.run(sourceDatabase, targetDatabase, transaction); - return null; - } - }; - } - - private void closeDatabase(Database database) - { - if (database != null) - { - try - { - database.close(); - } - catch (Exception e) - { - _logger.error("Unable to close database", e); - } - } - } - -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/StoreUpgrade.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/StoreUpgrade.java deleted file mode 100644 index 0ff90a6d77..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/StoreUpgrade.java +++ /dev/null @@ -1,30 +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.upgrade; - -import com.sleepycat.je.Environment; - -import org.apache.qpid.server.model.ConfiguredObject; - -public interface StoreUpgrade -{ - void performUpgrade(Environment environment, UpgradeInteractionHandler handler, ConfiguredObject<?> parent); -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4To5.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4To5.java deleted file mode 100644 index 05f0039b24..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4To5.java +++ /dev/null @@ -1,868 +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.upgrade; - -import java.io.ByteArrayInputStream; -import java.io.DataInputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import com.sleepycat.bind.tuple.ByteBinding; -import com.sleepycat.bind.tuple.LongBinding; -import com.sleepycat.bind.tuple.TupleBase; -import com.sleepycat.bind.tuple.TupleBinding; -import com.sleepycat.bind.tuple.TupleInput; -import com.sleepycat.bind.tuple.TupleOutput; -import com.sleepycat.je.Database; -import com.sleepycat.je.DatabaseEntry; -import com.sleepycat.je.Environment; -import com.sleepycat.je.Transaction; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.common.AMQPFilterTypes; -import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.framing.AMQFrameDecodingException; -import org.apache.qpid.framing.AMQProtocolVersionException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.framing.MessagePublishInfo; -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.protocol.v0_8.MessageMetaData; -import org.apache.qpid.server.store.StorableMessageMetaData; -import org.apache.qpid.server.store.StoreException; -import org.apache.qpid.server.store.berkeleydb.AMQShortStringEncoding; -import org.apache.qpid.server.store.berkeleydb.FieldTableEncoding; - -public class UpgradeFrom4To5 extends AbstractStoreUpgrade -{ - private static final String OLD_DELIVERY_DB = "deliveryDb_v4"; - private static final String NEW_DELIVERY_DB = "deliveryDb_v5"; - private static final String EXCHANGE_DB_NAME = "exchangeDb_v4"; - private static final String OLD_BINDINGS_DB_NAME = "queueBindingsDb_v4"; - private static final String NEW_BINDINGS_DB_NAME = "queueBindingsDb_v5"; - private static final String OLD_QUEUE_DB_NAME = "queueDb_v4"; - private static final String NEW_QUEUE_DB_NAME = "queueDb_v5"; - private static final String OLD_METADATA_DB_NAME = "messageMetaDataDb_v4"; - private static final String NEW_METADATA_DB_NAME = "messageMetaDataDb_v5"; - private static final String OLD_CONTENT_DB_NAME = "messageContentDb_v4"; - private static final String NEW_CONTENT_DB_NAME = "messageContentDb_v5"; - - private static final byte COLON = (byte) ':'; - - private static final Logger _logger = LoggerFactory.getLogger(UpgradeFrom4To5.class); - - public void performUpgrade(final Environment environment, final UpgradeInteractionHandler handler, ConfiguredObject<?> parent) - { - Transaction transaction = null; - reportStarting(environment, 4); - - transaction = environment.beginTransaction(null, null); - - // find all queues which are bound to a topic exchange and which have a colon in their name - final List<AMQShortString> potentialDurableSubs = findPotentialDurableSubscriptions(environment, transaction); - - Set<String> existingQueues = upgradeQueues(environment, handler, potentialDurableSubs, transaction); - upgradeQueueBindings(environment, handler, potentialDurableSubs, transaction); - Set<Long> messagesToDiscard = upgradeDelivery(environment, existingQueues, handler, transaction); - upgradeContent(environment, handler, messagesToDiscard, transaction); - upgradeMetaData(environment, handler, messagesToDiscard, transaction); - renameRemainingDatabases(environment, handler, transaction); - transaction.commit(); - - reportFinished(environment, 5); - } - - private void upgradeQueueBindings(Environment environment, UpgradeInteractionHandler handler, final List<AMQShortString> potentialDurableSubs, - Transaction transaction) - { - if (environment.getDatabaseNames().contains(OLD_BINDINGS_DB_NAME)) - { - _logger.info("Queue Bindings"); - final BindingTuple bindingTuple = new BindingTuple(); - CursorOperation databaseOperation = new CursorOperation() - { - - @Override - public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, - DatabaseEntry key, DatabaseEntry value) - { - // All the information required in binding entries is actually in the *key* not value. - BindingRecord oldBindingRecord = bindingTuple.entryToObject(key); - - AMQShortString queueName = oldBindingRecord.getQueueName(); - AMQShortString exchangeName = oldBindingRecord.getExchangeName(); - AMQShortString routingKey = oldBindingRecord.getRoutingKey(); - FieldTable arguments = oldBindingRecord.getArguments(); - - if (_logger.isDebugEnabled()) - { - _logger.debug(String.format( - "Processing binding for queue %s, exchange %s, routingKey %s arguments %s", queueName, - exchangeName, routingKey, arguments)); - } - - // if the queue name is in the gathered list then inspect its binding arguments - // only topic exchange should have a JMS selector key in binding - if (potentialDurableSubs.contains(queueName) - && exchangeName.equals(AMQShortString.valueOf(ExchangeDefaults.TOPIC_EXCHANGE_NAME))) - { - if (arguments == null) - { - arguments = new FieldTable(); - } - - AMQShortString selectorFilterKey = AMQPFilterTypes.JMS_SELECTOR.getValue(); - if (!arguments.containsKey(selectorFilterKey)) - { - if (_logger.isDebugEnabled()) - { - _logger.info("adding the empty string (i.e. 'no selector') value for " + queueName - + " and exchange " + exchangeName); - } - arguments.put(selectorFilterKey, ""); - } - } - addBindingToDatabase(bindingTuple, targetDatabase, transaction, queueName, exchangeName, routingKey, - arguments); - } - }; - new DatabaseTemplate(environment, OLD_BINDINGS_DB_NAME, NEW_BINDINGS_DB_NAME, transaction) - .run(databaseOperation); - environment.removeDatabase(transaction, OLD_BINDINGS_DB_NAME); - _logger.info(databaseOperation.getRowCount() + " Queue Binding entries"); - } - } - - private Set<String> upgradeQueues(final Environment environment, final UpgradeInteractionHandler handler, - List<AMQShortString> potentialDurableSubs, Transaction transaction) - { - _logger.info("Queues"); - final Set<String> existingQueues = new HashSet<String>(); - if (environment.getDatabaseNames().contains(OLD_QUEUE_DB_NAME)) - { - final QueueRecordBinding binding = new QueueRecordBinding(potentialDurableSubs); - CursorOperation databaseOperation = new CursorOperation() - { - @Override - public void processEntry(final Database sourceDatabase, final Database targetDatabase, - final Transaction transaction, final DatabaseEntry key, final DatabaseEntry value) - { - QueueRecord record = binding.entryToObject(value); - DatabaseEntry newValue = new DatabaseEntry(); - binding.objectToEntry(record, newValue); - targetDatabase.put(transaction, key, newValue); - existingQueues.add(record.getNameShortString().asString()); - sourceDatabase.delete(transaction, key); - } - }; - new DatabaseTemplate(environment, OLD_QUEUE_DB_NAME, NEW_QUEUE_DB_NAME, transaction).run(databaseOperation); - environment.removeDatabase(transaction, OLD_QUEUE_DB_NAME); - _logger.info(databaseOperation.getRowCount() + " Queue entries"); - } - return existingQueues; - } - - private List<AMQShortString> findPotentialDurableSubscriptions(final Environment environment, - Transaction transaction) - { - final List<AMQShortString> exchangeNames = findTopicExchanges(environment); - final List<AMQShortString> queues = new ArrayList<AMQShortString>(); - final PartialBindingRecordBinding binding = new PartialBindingRecordBinding(); - - CursorOperation databaseOperation = new CursorOperation() - { - @Override - public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, - DatabaseEntry key, DatabaseEntry value) - { - PartialBindingRecord record = binding.entryToObject(key); - if (exchangeNames.contains(record.getExchangeName()) && record.getQueueName().contains(COLON)) - { - queues.add(record.getQueueName()); - } - } - }; - new DatabaseTemplate(environment, OLD_BINDINGS_DB_NAME, transaction).run(databaseOperation); - return queues; - } - - private Set<Long> upgradeDelivery(final Environment environment, final Set<String> existingQueues, - final UpgradeInteractionHandler handler, Transaction transaction) - { - final Set<Long> messagesToDiscard = new HashSet<Long>(); - final Set<String> queuesToDiscard = new HashSet<String>(); - final QueueEntryKeyBinding queueEntryKeyBinding = new QueueEntryKeyBinding(); - _logger.info("Delivery Records"); - - CursorOperation databaseOperation = new CursorOperation() - { - @Override - public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, - DatabaseEntry key, DatabaseEntry value) - { - QueueEntryKey entryKey = queueEntryKeyBinding.entryToObject(key); - Long messageId = entryKey.getMessageId(); - final String queueName = entryKey.getQueueName().asString(); - if (!existingQueues.contains(queueName)) - { - if (queuesToDiscard.contains(queueName)) - { - messagesToDiscard.add(messageId); - } - else - { - String lineSeparator = System.getProperty("line.separator"); - String question = MessageFormat.format("Found persistent messages for non-durable queue ''{1}''. " - + " Do you with to create this queue and move all the messages into it?" + lineSeparator - + "NOTE: Answering No will result in these messages being discarded!", queueName); - UpgradeInteractionResponse response = handler.requireResponse(question.toString(), - UpgradeInteractionResponse.YES, UpgradeInteractionResponse.YES, - UpgradeInteractionResponse.NO, UpgradeInteractionResponse.ABORT); - - if (response == UpgradeInteractionResponse.YES) - { - createQueue(environment, transaction, queueName); - existingQueues.add(queueName); - } - else if (response == UpgradeInteractionResponse.NO) - { - queuesToDiscard.add(queueName); - messagesToDiscard.add(messageId); - } - else - { - throw new StoreException("Unable is aborted!"); - } - } - } - - if (!messagesToDiscard.contains(messageId)) - { - DatabaseEntry newKey = new DatabaseEntry(); - queueEntryKeyBinding.objectToEntry(entryKey, newKey); - targetDatabase.put(transaction, newKey, value); - - } - } - }; - new DatabaseTemplate(environment, OLD_DELIVERY_DB, NEW_DELIVERY_DB, transaction).run(databaseOperation); - - if (!messagesToDiscard.isEmpty()) - { - databaseOperation = new CursorOperation() - { - @Override - public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, - DatabaseEntry key, DatabaseEntry value) - { - QueueEntryKey entryKey = queueEntryKeyBinding.entryToObject(key); - Long messageId = entryKey.getMessageId(); - - if (messagesToDiscard.contains(messageId)) - { - messagesToDiscard.remove(messageId); - } - } - }; - new DatabaseTemplate(environment, NEW_DELIVERY_DB, transaction).run(databaseOperation); - } - _logger.info(databaseOperation.getRowCount() + " Delivery Records entries "); - environment.removeDatabase(transaction, OLD_DELIVERY_DB); - - return messagesToDiscard; - } - - protected void createQueue(final Environment environment, Transaction transaction, final String queueName) - { - - final QueueRecordBinding binding = new QueueRecordBinding(null); - final BindingTuple bindingTuple = new BindingTuple(); - DatabaseRunnable queueCreateOperation = new DatabaseRunnable() - { - - @Override - public void run(Database newQueueDatabase, Database newBindingsDatabase, Transaction transaction) - { - AMQShortString queueNameAMQ = new AMQShortString(queueName); - QueueRecord record = new QueueRecord(queueNameAMQ, null, false, null); - - DatabaseEntry key = new DatabaseEntry(); - - TupleOutput output = new TupleOutput(); - AMQShortStringEncoding.writeShortString(record.getNameShortString(), output); - TupleBase.outputToEntry(output, key); - - DatabaseEntry newValue = new DatabaseEntry(); - binding.objectToEntry(record, newValue); - newQueueDatabase.put(transaction, key, newValue); - - FieldTable emptyArguments = new FieldTable(); - addBindingToDatabase(bindingTuple, newBindingsDatabase, transaction, queueNameAMQ, - AMQShortString.valueOf(ExchangeDefaults.DIRECT_EXCHANGE_NAME), queueNameAMQ, emptyArguments); - - // TODO QPID-3490 we should not persist a default exchange binding - addBindingToDatabase(bindingTuple, newBindingsDatabase, transaction, queueNameAMQ, - AMQShortString.valueOf(ExchangeDefaults.DEFAULT_EXCHANGE_NAME), queueNameAMQ, emptyArguments); - } - }; - new DatabaseTemplate(environment, NEW_QUEUE_DB_NAME, NEW_BINDINGS_DB_NAME, transaction).run(queueCreateOperation); - } - - private List<AMQShortString> findTopicExchanges(final Environment environment) - { - final List<AMQShortString> topicExchanges = new ArrayList<AMQShortString>(); - final ExchangeRecordBinding binding = new ExchangeRecordBinding(); - CursorOperation databaseOperation = new CursorOperation() - { - - @Override - public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, - DatabaseEntry key, DatabaseEntry value) - { - ExchangeRecord record = binding.entryToObject(value); - if (AMQShortString.valueOf(ExchangeDefaults.TOPIC_EXCHANGE_CLASS).equals(record.getType())) - { - topicExchanges.add(record.getName()); - } - } - }; - new DatabaseTemplate(environment, EXCHANGE_DB_NAME, null).run(databaseOperation); - return topicExchanges; - } - - private void upgradeMetaData(final Environment environment, final UpgradeInteractionHandler handler, - final Set<Long> messagesToDiscard, Transaction transaction) - { - _logger.info("Message MetaData"); - if (environment.getDatabaseNames().contains(OLD_METADATA_DB_NAME)) - { - final MessageMetaDataBinding binding = new MessageMetaDataBinding(); - CursorOperation databaseOperation = new CursorOperation() - { - - @Override - public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, - DatabaseEntry key, DatabaseEntry value) - { - StorableMessageMetaData metaData = binding.entryToObject(value); - - // get message id - Long messageId = LongBinding.entryToLong(key); - - // ONLY copy data if message is delivered to existing queue - if (messagesToDiscard.contains(messageId)) - { - return; - } - DatabaseEntry newValue = new DatabaseEntry(); - binding.objectToEntry(metaData, newValue); - - targetDatabase.put(transaction, key, newValue); - targetDatabase.put(transaction, key, newValue); - deleteCurrent(); - - } - }; - - new DatabaseTemplate(environment, OLD_METADATA_DB_NAME, NEW_METADATA_DB_NAME, transaction) - .run(databaseOperation); - environment.removeDatabase(transaction, OLD_METADATA_DB_NAME); - _logger.info(databaseOperation.getRowCount() + " Message MetaData entries"); - } - } - - private void upgradeContent(final Environment environment, final UpgradeInteractionHandler handler, - final Set<Long> messagesToDiscard, Transaction transaction) - { - _logger.info("Message Contents"); - if (environment.getDatabaseNames().contains(OLD_CONTENT_DB_NAME)) - { - final MessageContentKeyBinding keyBinding = new MessageContentKeyBinding(); - final ContentBinding contentBinding = new ContentBinding(); - CursorOperation cursorOperation = new CursorOperation() - { - private long _prevMsgId = -1; - private int _bytesSeenSoFar; - - @Override - public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, - DatabaseEntry key, DatabaseEntry value) - { - // determine the msgId of the current entry - MessageContentKey contentKey = keyBinding.entryToObject(key); - long msgId = contentKey.getMessageId(); - - // ONLY copy data if message is delivered to existing queue - if (messagesToDiscard.contains(msgId)) - { - return; - } - // if this is a new message, restart the byte offset count. - if (_prevMsgId != msgId) - { - _bytesSeenSoFar = 0; - } - - // determine the content size - ByteBuffer content = contentBinding.entryToObject(value); - int contentSize = content.limit(); - - // create the new key: id + previously seen data count - MessageContentKey newKey = new MessageContentKey(msgId, _bytesSeenSoFar); - DatabaseEntry newKeyEntry = new DatabaseEntry(); - keyBinding.objectToEntry(newKey, newKeyEntry); - - DatabaseEntry newValueEntry = new DatabaseEntry(); - contentBinding.objectToEntry(content, newValueEntry); - - targetDatabase.put(null, newKeyEntry, newValueEntry); - - _prevMsgId = msgId; - _bytesSeenSoFar += contentSize; - } - }; - new DatabaseTemplate(environment, OLD_CONTENT_DB_NAME, NEW_CONTENT_DB_NAME, transaction).run(cursorOperation); - environment.removeDatabase(transaction, OLD_CONTENT_DB_NAME); - _logger.info(cursorOperation.getRowCount() + " Message Content entries"); - } - } - - /** - * For all databases which haven't been otherwise upgraded, we still need to - * rename them from _v4 to _v5 - */ - private void renameRemainingDatabases(final Environment environment, final UpgradeInteractionHandler handler, - Transaction transaction) - { - for (String dbName : environment.getDatabaseNames()) - { - if (dbName.endsWith("_v4")) - { - String newName = dbName.substring(0, dbName.length() - 3) + "_v5"; - _logger.info("Renaming " + dbName + " into " + newName); - environment.renameDatabase(transaction, dbName, newName); - } - } - - } - - private void addBindingToDatabase(final BindingTuple bindingTuple, Database targetDatabase, Transaction transaction, - AMQShortString queueName, AMQShortString exchangeName, AMQShortString routingKey, FieldTable arguments) - { - - DatabaseEntry newKey = new DatabaseEntry(); - - bindingTuple.objectToEntry(new BindingRecord(exchangeName, queueName, routingKey, arguments), newKey); - - DatabaseEntry newValue = new DatabaseEntry(); - ByteBinding.byteToEntry((byte) 0, newValue); - - targetDatabase.put(transaction, newKey, newValue); - } - - private static final class ExchangeRecord - { - private final AMQShortString _name; - private final AMQShortString _type; - - private ExchangeRecord(final AMQShortString name, final AMQShortString type) - { - _name = name; - _type = type; - } - - public AMQShortString getName() - { - return _name; - } - - public AMQShortString getType() - { - return _type; - } - } - - private static final class ExchangeRecordBinding extends TupleBinding<ExchangeRecord> - { - - @Override - public ExchangeRecord entryToObject(final TupleInput input) - { - return new ExchangeRecord(AMQShortStringEncoding.readShortString(input), - AMQShortStringEncoding.readShortString(input)); - } - - @Override - public void objectToEntry(final ExchangeRecord object, final TupleOutput output) - { - AMQShortStringEncoding.writeShortString(object.getName(), output); - AMQShortStringEncoding.writeShortString(object.getType(), output); - output.writeBoolean(false); - } - } - - private static final class PartialBindingRecord - { - private final AMQShortString _exchangeName; - private final AMQShortString _queueName; - - private PartialBindingRecord(final AMQShortString name, final AMQShortString type) - { - _exchangeName = name; - _queueName = type; - } - - public AMQShortString getExchangeName() - { - return _exchangeName; - } - - public AMQShortString getQueueName() - { - return _queueName; - } - } - - private static final class PartialBindingRecordBinding extends TupleBinding<PartialBindingRecord> - { - - @Override - public PartialBindingRecord entryToObject(final TupleInput input) - { - return new PartialBindingRecord(AMQShortStringEncoding.readShortString(input), - AMQShortStringEncoding.readShortString(input)); - } - - @Override - public void objectToEntry(final PartialBindingRecord object, final TupleOutput output) - { - throw new UnsupportedOperationException(); - } - } - - static final class QueueRecord - { - private final AMQShortString _queueName; - private final AMQShortString _owner; - private final FieldTable _arguments; - private final boolean _exclusive; - - public QueueRecord(AMQShortString queueName, AMQShortString owner, boolean exclusive, FieldTable arguments) - { - _queueName = queueName; - _owner = owner; - _exclusive = exclusive; - _arguments = arguments; - } - - public AMQShortString getNameShortString() - { - return _queueName; - } - - public AMQShortString getOwner() - { - return _owner; - } - - public boolean isExclusive() - { - return _exclusive; - } - - public FieldTable getArguments() - { - return _arguments; - } - } - - static final class QueueRecordBinding extends TupleBinding<QueueRecord> - { - private final List<AMQShortString> _durableSubNames; - - QueueRecordBinding(final List<AMQShortString> durableSubNames) - { - _durableSubNames = durableSubNames; - } - - @Override - public QueueRecord entryToObject(final TupleInput input) - { - AMQShortString name = AMQShortStringEncoding.readShortString(input); - AMQShortString owner = AMQShortStringEncoding.readShortString(input); - FieldTable arguments = FieldTableEncoding.readFieldTable(input); - boolean exclusive = input.available() > 0 && input.readBoolean(); - exclusive = exclusive || _durableSubNames.contains(name); - - return new QueueRecord(name, owner, exclusive, arguments); - - } - - @Override - public void objectToEntry(final QueueRecord record, final TupleOutput output) - { - AMQShortStringEncoding.writeShortString(record.getNameShortString(), output); - AMQShortStringEncoding.writeShortString(record.getOwner(), output); - FieldTableEncoding.writeFieldTable(record.getArguments(), output); - output.writeBoolean(record.isExclusive()); - - } - } - - static final class MessageMetaDataBinding extends TupleBinding<StorableMessageMetaData> - { - - @Override - public MessageMetaData entryToObject(final TupleInput input) - { - try - { - final MessagePublishInfo publishBody = readMessagePublishInfo(input); - final ContentHeaderBody contentHeaderBody = readContentHeaderBody(input); - - return new MessageMetaData(publishBody, contentHeaderBody); - } - catch (Exception e) - { - _logger.error("Error converting entry to object: " + e, e); - // annoyingly just have to return null since we cannot throw - return null; - } - } - - private MessagePublishInfo readMessagePublishInfo(TupleInput tupleInput) - { - - final AMQShortString exchange = AMQShortStringEncoding.readShortString(tupleInput); - final AMQShortString routingKey = AMQShortStringEncoding.readShortString(tupleInput); - final boolean mandatory = tupleInput.readBoolean(); - final boolean immediate = tupleInput.readBoolean(); - - return new MessagePublishInfo(exchange, immediate, mandatory, routingKey); - - } - - private ContentHeaderBody readContentHeaderBody(TupleInput tupleInput) throws AMQFrameDecodingException, - AMQProtocolVersionException - { - int bodySize = tupleInput.readInt(); - byte[] underlying = new byte[bodySize]; - tupleInput.readFast(underlying); - - try - { - return ContentHeaderBody.createFromBuffer(new DataInputStream(new ByteArrayInputStream(underlying)), - bodySize); - } - catch (IOException e) - { - throw new AMQFrameDecodingException(null, e.getMessage(), e); - } - } - - @Override - public void objectToEntry(final StorableMessageMetaData metaData, final TupleOutput output) - { - final int bodySize = 1 + metaData.getStorableSize(); - byte[] underlying = new byte[bodySize]; - underlying[0] = (byte) metaData.getType().ordinal(); - java.nio.ByteBuffer buf = java.nio.ByteBuffer.wrap(underlying); - buf.position(1); - buf = buf.slice(); - - metaData.writeToBuffer(buf); - output.writeInt(bodySize); - output.writeFast(underlying); - } - } - - static final class MessageContentKey - { - private long _messageId; - private int _chunk; - - public MessageContentKey(long messageId, int chunkNo) - { - _messageId = messageId; - _chunk = chunkNo; - } - - public int getChunk() - { - return _chunk; - } - - public long getMessageId() - { - return _messageId; - } - - } - - static final class MessageContentKeyBinding extends TupleBinding<MessageContentKey> - { - - public MessageContentKey entryToObject(TupleInput tupleInput) - { - long messageId = tupleInput.readLong(); - int chunk = tupleInput.readInt(); - return new MessageContentKey(messageId, chunk); - } - - public void objectToEntry(MessageContentKey object, TupleOutput tupleOutput) - { - final MessageContentKey mk = object; - tupleOutput.writeLong(mk.getMessageId()); - tupleOutput.writeInt(mk.getChunk()); - } - - } - - static final class ContentBinding extends TupleBinding<ByteBuffer> - { - public ByteBuffer entryToObject(TupleInput tupleInput) - { - final int size = tupleInput.readInt(); - byte[] underlying = new byte[size]; - tupleInput.readFast(underlying); - return ByteBuffer.wrap(underlying); - } - - public void objectToEntry(ByteBuffer src, TupleOutput tupleOutput) - { - src = src.slice(); - - byte[] chunkData = new byte[src.limit()]; - src.duplicate().get(chunkData); - - tupleOutput.writeInt(chunkData.length); - tupleOutput.writeFast(chunkData); - } - } - - static final class QueueEntryKey - { - private AMQShortString _queueName; - private long _messageId; - - public QueueEntryKey(AMQShortString queueName, long messageId) - { - _queueName = queueName; - _messageId = messageId; - } - - public AMQShortString getQueueName() - { - return _queueName; - } - - public long getMessageId() - { - return _messageId; - } - - } - - static final class QueueEntryKeyBinding extends TupleBinding<QueueEntryKey> - { - public QueueEntryKey entryToObject(TupleInput tupleInput) - { - AMQShortString queueName = AMQShortStringEncoding.readShortString(tupleInput); - long messageId = tupleInput.readLong(); - return new QueueEntryKey(queueName, messageId); - } - - public void objectToEntry(QueueEntryKey mk, TupleOutput tupleOutput) - { - AMQShortStringEncoding.writeShortString(mk.getQueueName(), tupleOutput); - tupleOutput.writeLong(mk.getMessageId()); - } - } - - static final class BindingRecord extends Object - { - private final AMQShortString _exchangeName; - private final AMQShortString _queueName; - private final AMQShortString _routingKey; - private final FieldTable _arguments; - - public BindingRecord(AMQShortString exchangeName, AMQShortString queueName, AMQShortString routingKey, - FieldTable arguments) - { - _exchangeName = exchangeName; - _queueName = queueName; - _routingKey = routingKey; - _arguments = arguments; - } - - public AMQShortString getExchangeName() - { - return _exchangeName; - } - - public AMQShortString getQueueName() - { - return _queueName; - } - - public AMQShortString getRoutingKey() - { - return _routingKey; - } - - public FieldTable getArguments() - { - return _arguments; - } - - } - - static final class BindingTuple extends TupleBinding<BindingRecord> - { - public BindingRecord entryToObject(TupleInput tupleInput) - { - AMQShortString exchangeName = AMQShortStringEncoding.readShortString(tupleInput); - AMQShortString queueName = AMQShortStringEncoding.readShortString(tupleInput); - AMQShortString routingKey = AMQShortStringEncoding.readShortString(tupleInput); - - FieldTable arguments = FieldTableEncoding.readFieldTable(tupleInput); - - return new BindingRecord(exchangeName, queueName, routingKey, arguments); - } - - public void objectToEntry(BindingRecord binding, TupleOutput tupleOutput) - { - AMQShortStringEncoding.writeShortString(binding.getExchangeName(), tupleOutput); - AMQShortStringEncoding.writeShortString(binding.getQueueName(), tupleOutput); - AMQShortStringEncoding.writeShortString(binding.getRoutingKey(), tupleOutput); - - FieldTableEncoding.writeFieldTable(binding.getArguments(), tupleOutput); - } - - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java deleted file mode 100644 index 40b0afb9a1..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java +++ /dev/null @@ -1,1204 +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.upgrade; - -import static org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeInteractionResponse.ABORT; -import static org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeInteractionResponse.NO; -import static org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeInteractionResponse.YES; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedMap; -import java.util.TreeMap; -import java.util.UUID; - -import com.sleepycat.bind.tuple.LongBinding; -import com.sleepycat.bind.tuple.TupleBinding; -import com.sleepycat.bind.tuple.TupleInput; -import com.sleepycat.bind.tuple.TupleOutput; -import com.sleepycat.je.Cursor; -import com.sleepycat.je.CursorConfig; -import com.sleepycat.je.Database; -import com.sleepycat.je.DatabaseEntry; -import com.sleepycat.je.Environment; -import com.sleepycat.je.LockMode; -import com.sleepycat.je.OperationStatus; -import com.sleepycat.je.Transaction; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.model.Binding; -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.model.Exchange; -import org.apache.qpid.server.model.LifetimePolicy; -import org.apache.qpid.server.model.Queue; -import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.queue.QueueArgumentsConverter; -import org.apache.qpid.server.store.StoreException; -import org.apache.qpid.server.store.berkeleydb.AMQShortStringEncoding; -import org.apache.qpid.server.store.berkeleydb.FieldTableEncoding; -import org.apache.qpid.server.util.MapJsonSerializer; - -public class UpgradeFrom5To6 extends AbstractStoreUpgrade -{ - - private static final Logger _logger = LoggerFactory.getLogger(UpgradeFrom5To6.class); - - static final String OLD_CONTENT_DB_NAME = "messageContentDb_v5"; - static final String NEW_CONTENT_DB_NAME = "MESSAGE_CONTENT"; - static final String NEW_METADATA_DB_NAME = "MESSAGE_METADATA"; - static final String OLD_META_DATA_DB_NAME = "messageMetaDataDb_v5"; - static final String OLD_EXCHANGE_DB_NAME = "exchangeDb_v5"; - static final String OLD_QUEUE_DB_NAME = "queueDb_v5"; - static final String OLD_DELIVERY_DB_NAME = "deliveryDb_v5"; - static final String OLD_QUEUE_BINDINGS_DB_NAME = "queueBindingsDb_v5"; - static final String OLD_XID_DB_NAME = "xids_v5"; - static final String NEW_XID_DB_NAME = "XIDS"; - static final String CONFIGURED_OBJECTS_DB_NAME = "CONFIGURED_OBJECTS"; - static final String NEW_DELIVERY_DB_NAME = "QUEUE_ENTRIES"; - static final String NEW_BRIDGES_DB_NAME = "BRIDGES"; - static final String NEW_LINKS_DB_NAME = "LINKS"; - static final String OLD_BRIDGES_DB_NAME = "bridges_v5"; - static final String OLD_LINKS_DB_NAME = "links_v5"; - - private static final Set<String> DEFAULT_EXCHANGES_SET = - new HashSet<String>(Arrays.asList( - ExchangeDefaults.DEFAULT_EXCHANGE_NAME, - ExchangeDefaults.FANOUT_EXCHANGE_NAME, - ExchangeDefaults.HEADERS_EXCHANGE_NAME, - ExchangeDefaults.TOPIC_EXCHANGE_NAME, - ExchangeDefaults.DIRECT_EXCHANGE_NAME)); - - private static final String ARGUMENTS = "arguments"; - - private MapJsonSerializer _serializer = new MapJsonSerializer(); - - private static final boolean _moveNonExclusiveQueueOwnerToDescription = Boolean.parseBoolean(System.getProperty("qpid.move_non_exclusive_queue_owner_to_description", Boolean.TRUE.toString())); - - /** - * Upgrades from a v5 database to a v6 database - * - * v6 is the first "new style" schema where we don't version every table, - * and the upgrade is re-runnable - * - * Change in this version: - * - * Message content is moved from the database messageContentDb_v5 to - * MESSAGE_CONTENT. The structure of the database changes from ( message-id: - * long, chunk-id: int ) {@literal ->} ( size: int, byte[] data ) to ( message-id: - * long) {@literal ->} ( byte[] data ) - * - * That is we keep only one record per message, which contains all the - * message content - * - * Queue, Exchange, Bindings entries are stored now as configurable objects - * in "CONFIGURED_OBJECTS" table. - */ - public void performUpgrade(final Environment environment, final UpgradeInteractionHandler handler, ConfiguredObject<?> parent) - { - reportStarting(environment, 5); - upgradeMessages(environment, handler); - upgradeConfiguredObjectsAndDependencies(environment, handler, parent.getName()); - renameDatabases(environment, null); - reportFinished(environment, 6); - } - - private void upgradeConfiguredObjectsAndDependencies(Environment environment, UpgradeInteractionHandler handler, String virtualHostName) - { - Transaction transaction = null; - transaction = environment.beginTransaction(null, null); - upgradeConfiguredObjects(environment, handler, transaction, virtualHostName); - upgradeQueueEntries(environment, transaction, virtualHostName); - upgradeXidEntries(environment, transaction, virtualHostName); - transaction.commit(); - } - - private void upgradeMessages(final Environment environment, final UpgradeInteractionHandler handler) - { - Transaction transaction = null; - transaction = environment.beginTransaction(null, null); - upgradeMessages(environment, handler, transaction); - transaction.commit(); - } - - private void renameDatabases(Environment environment, Transaction transaction) - { - List<String> databases = environment.getDatabaseNames(); - String[] oldDatabases = { OLD_META_DATA_DB_NAME, OLD_BRIDGES_DB_NAME, OLD_LINKS_DB_NAME }; - String[] newDatabases = { NEW_METADATA_DB_NAME, NEW_BRIDGES_DB_NAME, NEW_LINKS_DB_NAME }; - - for (int i = 0; i < oldDatabases.length; i++) - { - String oldName = oldDatabases[i]; - String newName = newDatabases[i]; - if (databases.contains(oldName)) - { - _logger.info("Renaming " + oldName + " into " + newName); - environment.renameDatabase(transaction, oldName, newName); - } - } - } - - private void upgradeMessages(final Environment environment, final UpgradeInteractionHandler handler, - final Transaction transaction) - { - _logger.info("Message Contents"); - if (environment.getDatabaseNames().contains(OLD_CONTENT_DB_NAME)) - { - DatabaseRunnable contentOperation = new DatabaseRunnable() - { - @Override - public void run(final Database oldContentDatabase, final Database newContentDatabase, - Transaction contentTransaction) - { - CursorOperation metaDataDatabaseOperation = new CursorOperation() - { - - @Override - public void processEntry(Database metadataDatabase, Database notUsed, - Transaction metaDataTransaction, DatabaseEntry key, DatabaseEntry value) - { - long messageId = LongBinding.entryToLong(key); - upgradeMessage(messageId, oldContentDatabase, newContentDatabase, handler, metaDataTransaction, - metadataDatabase); - } - }; - new DatabaseTemplate(environment, OLD_META_DATA_DB_NAME, contentTransaction) - .run(metaDataDatabaseOperation); - _logger.info(metaDataDatabaseOperation.getRowCount() + " Message Content Entries"); - } - }; - new DatabaseTemplate(environment, OLD_CONTENT_DB_NAME, NEW_CONTENT_DB_NAME, transaction).run(contentOperation); - environment.removeDatabase(transaction, OLD_CONTENT_DB_NAME); - } - } - - /** - * Upgrade an individual message, that is read all the data from the old - * database, consolidate it into a single byte[] and then (in a transaction) - * remove the record from the old database and add the corresponding record - * to the new database - */ - private void upgradeMessage(final long messageId, final Database oldDatabase, final Database newDatabase, - final UpgradeInteractionHandler handler, Transaction txn, Database oldMetadataDatabase) - { - SortedMap<Integer, byte[]> messageData = getMessageData(messageId, oldDatabase); - byte[] consolidatedData = new byte[0]; - for (Map.Entry<Integer, byte[]> entry : messageData.entrySet()) - { - int offset = entry.getKey(); - if (offset != consolidatedData.length) - { - String message; - if (offset < consolidatedData.length) - { - message = "Missing data in message id " + messageId + " between offset " + consolidatedData.length - + " and " + offset + ". "; - } - else - { - message = "Duplicate data in message id " + messageId + " between offset " + offset + " and " - + consolidatedData.length + ". "; - } - UpgradeInteractionResponse action = handler.requireResponse(message - + "Do you wish do recover as much of this message as " - + "possible (answering NO will delete the message)?", ABORT, YES, NO, ABORT); - - switch (action) - { - case YES: - byte[] oldData = consolidatedData; - consolidatedData = new byte[offset]; - System.arraycopy(oldData, 0, consolidatedData, 0, Math.min(oldData.length, consolidatedData.length)); - break; - case NO: - DatabaseEntry key = new DatabaseEntry(); - LongBinding.longToEntry(messageId, key); - oldMetadataDatabase.delete(txn, key); - return; - case ABORT: - _logger.error(message); - throw new StoreException("Unable to upgrade message " + messageId); - } - - } - byte[] data = new byte[consolidatedData.length + entry.getValue().length]; - System.arraycopy(consolidatedData, 0, data, 0, consolidatedData.length); - System.arraycopy(entry.getValue(), 0, data, offset, entry.getValue().length); - consolidatedData = data; - } - - CompoundKeyBinding binding = new CompoundKeyBinding(); - for (int offset : messageData.keySet()) - { - DatabaseEntry key = new DatabaseEntry(); - binding.objectToEntry(new CompoundKey(messageId, offset), key); - oldDatabase.delete(txn, key); - } - DatabaseEntry key = new DatabaseEntry(); - LongBinding.longToEntry(messageId, key); - NewDataBinding dataBinding = new NewDataBinding(); - DatabaseEntry value = new DatabaseEntry(); - dataBinding.objectToEntry(consolidatedData, value); - - put(newDatabase, txn, key, value); - } - - /** - * @return a (sorted) map of offset -> data for the given message id - */ - private SortedMap<Integer, byte[]> getMessageData(final long messageId, final Database oldDatabase) - { - TreeMap<Integer, byte[]> data = new TreeMap<Integer, byte[]>(); - - Cursor cursor = oldDatabase.openCursor(null, CursorConfig.READ_COMMITTED); - try - { - DatabaseEntry contentKeyEntry = new DatabaseEntry(); - DatabaseEntry value = new DatabaseEntry(); - CompoundKeyBinding binding = new CompoundKeyBinding(); - binding.objectToEntry(new CompoundKey(messageId, 0), contentKeyEntry); - - OperationStatus status = cursor.getSearchKeyRange(contentKeyEntry, value, LockMode.DEFAULT); - OldDataBinding dataBinding = new OldDataBinding(); - - while (status == OperationStatus.SUCCESS) - { - CompoundKey compoundKey = binding.entryToObject(contentKeyEntry); - long id = compoundKey.getMessageId(); - - if (id != messageId) - { - // we have exhausted all chunks for this message id, break - break; - } - - int offsetInMessage = compoundKey.getOffset(); - OldDataValue dataValue = dataBinding.entryToObject(value); - data.put(offsetInMessage, dataValue.getData()); - - status = cursor.getNext(contentKeyEntry, value, LockMode.DEFAULT); - } - } - finally - { - cursor.close(); - } - - return data; - } - - private void upgradeConfiguredObjects(Environment environment, UpgradeInteractionHandler handler, Transaction transaction, String virtualHostName) - { - upgradeQueues(environment, transaction, virtualHostName); - upgradeExchanges(environment, transaction, virtualHostName); - upgradeQueueBindings(environment, transaction, handler, virtualHostName); - } - - private void upgradeXidEntries(Environment environment, Transaction transaction, final String virtualHostName) - { - if (environment.getDatabaseNames().contains(OLD_XID_DB_NAME)) - { - _logger.info("Xid Records"); - final OldPreparedTransactionBinding oldTransactionBinding = new OldPreparedTransactionBinding(); - final NewPreparedTransactionBinding newTransactionBinding = new NewPreparedTransactionBinding(); - CursorOperation xidEntriesCursor = new CursorOperation() - { - @Override - public void processEntry(Database oldXidDatabase, Database newXidDatabase, Transaction transaction, - DatabaseEntry key, DatabaseEntry value) - { - OldPreparedTransaction oldPreparedTransaction = oldTransactionBinding.entryToObject(value); - OldRecordImpl[] oldDequeues = oldPreparedTransaction.getDequeues(); - OldRecordImpl[] oldEnqueues = oldPreparedTransaction.getEnqueues(); - - NewRecordImpl[] newEnqueues = null; - NewRecordImpl[] newDequeues = null; - if (oldDequeues != null) - { - newDequeues = new NewRecordImpl[oldDequeues.length]; - for (int i = 0; i < newDequeues.length; i++) - { - OldRecordImpl dequeue = oldDequeues[i]; - UUID id = UUIDGenerator.generateQueueUUID(dequeue.getQueueName(), virtualHostName); - newDequeues[i] = new NewRecordImpl(id, dequeue.getMessageNumber()); - } - } - if (oldEnqueues != null) - { - newEnqueues = new NewRecordImpl[oldEnqueues.length]; - for (int i = 0; i < newEnqueues.length; i++) - { - OldRecordImpl enqueue = oldEnqueues[i]; - UUID id = UUIDGenerator.generateQueueUUID(enqueue.getQueueName(), virtualHostName); - newEnqueues[i] = new NewRecordImpl(id, enqueue.getMessageNumber()); - } - } - NewPreparedTransaction newPreparedTransaction = new NewPreparedTransaction(newEnqueues, newDequeues); - DatabaseEntry newValue = new DatabaseEntry(); - newTransactionBinding.objectToEntry(newPreparedTransaction, newValue); - put(newXidDatabase, transaction, key, newValue); - } - }; - new DatabaseTemplate(environment, OLD_XID_DB_NAME, NEW_XID_DB_NAME, transaction).run(xidEntriesCursor); - environment.removeDatabase(transaction, OLD_XID_DB_NAME); - _logger.info(xidEntriesCursor.getRowCount() + " Xid Entries"); - } - } - - private void upgradeQueueEntries(Environment environment, Transaction transaction, final String virtualHostName) - { - _logger.info("Queue Delivery Records"); - if (environment.getDatabaseNames().contains(OLD_DELIVERY_DB_NAME)) - { - final OldQueueEntryBinding oldBinding = new OldQueueEntryBinding(); - final NewQueueEntryBinding newBinding = new NewQueueEntryBinding(); - CursorOperation queueEntriesCursor = new CursorOperation() - { - @Override - public void processEntry(Database oldDeliveryDatabase, Database newDeliveryDatabase, - Transaction transaction, DatabaseEntry key, DatabaseEntry value) - { - OldQueueEntryKey oldEntryRecord = oldBinding.entryToObject(key); - UUID queueId = UUIDGenerator.generateQueueUUID(oldEntryRecord.getQueueName().asString(), virtualHostName); - - NewQueueEntryKey newEntryRecord = new NewQueueEntryKey(queueId, oldEntryRecord.getMessageId()); - DatabaseEntry newKey = new DatabaseEntry(); - newBinding.objectToEntry(newEntryRecord, newKey); - put(newDeliveryDatabase, transaction, newKey, value); - } - }; - new DatabaseTemplate(environment, OLD_DELIVERY_DB_NAME, NEW_DELIVERY_DB_NAME, transaction) - .run(queueEntriesCursor); - environment.removeDatabase(transaction, OLD_DELIVERY_DB_NAME); - _logger.info(queueEntriesCursor.getRowCount() + " Queue Delivery Record Entries"); - } - } - - private void upgradeQueueBindings(Environment environment, Transaction transaction, final UpgradeInteractionHandler handler, final String virtualHostName) - { - _logger.info("Queue Bindings"); - if (environment.getDatabaseNames().contains(OLD_QUEUE_BINDINGS_DB_NAME)) - { - final QueueBindingBinding binding = new QueueBindingBinding(); - CursorOperation bindingCursor = new CursorOperation() - { - @Override - public void processEntry(Database exchangeDatabase, Database configuredObjectsDatabase, - Transaction transaction, DatabaseEntry key, DatabaseEntry value) - { - // TODO: check and remove orphaned bindings - BindingRecord bindingRecord = binding.entryToObject(key); - String exchangeName = bindingRecord.getExchangeName() == null ? ExchangeDefaults.DEFAULT_EXCHANGE_NAME : bindingRecord.getExchangeName().asString(); - String queueName = bindingRecord.getQueueName().asString(); - String routingKey = bindingRecord.getRoutingKey().asString(); - FieldTable arguments = bindingRecord.getArguments(); - - UUID bindingId = UUIDGenerator.generateBindingUUID(exchangeName, queueName, routingKey, virtualHostName); - UpgradeConfiguredObjectRecord configuredObject = createBindingConfiguredObjectRecord(exchangeName, queueName, - routingKey, arguments, virtualHostName); - storeConfiguredObjectEntry(configuredObjectsDatabase, bindingId, configuredObject, transaction); - } - - }; - new DatabaseTemplate(environment, OLD_QUEUE_BINDINGS_DB_NAME, CONFIGURED_OBJECTS_DB_NAME, transaction) - .run(bindingCursor); - environment.removeDatabase(transaction, OLD_QUEUE_BINDINGS_DB_NAME); - _logger.info(bindingCursor.getRowCount() + " Queue Binding Entries"); - } - } - - private List<String> upgradeExchanges(Environment environment, Transaction transaction, final String virtualHostName) - { - final List<String> exchangeNames = new ArrayList<String>(); - _logger.info("Exchanges"); - if (environment.getDatabaseNames().contains(OLD_EXCHANGE_DB_NAME)) - { - final ExchangeBinding exchangeBinding = new ExchangeBinding(); - CursorOperation exchangeCursor = new CursorOperation() - { - @Override - public void processEntry(Database exchangeDatabase, Database configuredObjectsDatabase, - Transaction transaction, DatabaseEntry key, DatabaseEntry value) - { - ExchangeRecord exchangeRecord = exchangeBinding.entryToObject(value); - String exchangeName = exchangeRecord.getNameShortString().asString(); - if (!DEFAULT_EXCHANGES_SET.contains(exchangeName) && !"<<default>>".equals(exchangeName)) - { - String exchangeType = exchangeRecord.getType().asString(); - boolean autoDelete = exchangeRecord.isAutoDelete(); - - UUID exchangeId = UUIDGenerator.generateExchangeUUID(exchangeName, virtualHostName); - - UpgradeConfiguredObjectRecord configuredObject = createExchangeConfiguredObjectRecord(exchangeName, - exchangeType, autoDelete); - storeConfiguredObjectEntry(configuredObjectsDatabase, exchangeId, configuredObject, transaction); - exchangeNames.add(exchangeName); - } - } - }; - new DatabaseTemplate(environment, OLD_EXCHANGE_DB_NAME, CONFIGURED_OBJECTS_DB_NAME, transaction) - .run(exchangeCursor); - environment.removeDatabase(transaction, OLD_EXCHANGE_DB_NAME); - _logger.info(exchangeCursor.getRowCount() + " Exchange Entries"); - } - return exchangeNames; - } - - private List<String> upgradeQueues(Environment environment, Transaction transaction, final String virtualHostName) - { - final List<String> queueNames = new ArrayList<String>(); - _logger.info("Queues"); - if (environment.getDatabaseNames().contains(OLD_QUEUE_DB_NAME)) - { - final UpgradeQueueBinding queueBinding = new UpgradeQueueBinding(); - CursorOperation queueCursor = new CursorOperation() - { - @Override - public void processEntry(Database queueDatabase, Database configuredObjectsDatabase, - Transaction transaction, DatabaseEntry key, DatabaseEntry value) - { - OldQueueRecord queueRecord = queueBinding.entryToObject(value); - String queueName = queueRecord.getNameShortString().asString(); - queueNames.add(queueName); - String owner = queueRecord.getOwner() == null ? null : queueRecord.getOwner().asString(); - boolean exclusive = queueRecord.isExclusive(); - FieldTable arguments = queueRecord.getArguments(); - - UUID queueId = UUIDGenerator.generateQueueUUID(queueName, virtualHostName); - UpgradeConfiguredObjectRecord configuredObject = createQueueConfiguredObjectRecord(queueName, owner, exclusive, - arguments); - storeConfiguredObjectEntry(configuredObjectsDatabase, queueId, configuredObject, transaction); - } - }; - new DatabaseTemplate(environment, OLD_QUEUE_DB_NAME, CONFIGURED_OBJECTS_DB_NAME, transaction).run(queueCursor); - environment.removeDatabase(transaction, OLD_QUEUE_DB_NAME); - _logger.info(queueCursor.getRowCount() + " Queue Entries"); - } - return queueNames; - } - - private void storeConfiguredObjectEntry(Database configuredObjectsDatabase, UUID id, - UpgradeConfiguredObjectRecord configuredObject, Transaction transaction) - { - DatabaseEntry key = new DatabaseEntry(); - DatabaseEntry value = new DatabaseEntry(); - UpgradeUUIDBinding uuidBinding = new UpgradeUUIDBinding(); - uuidBinding.objectToEntry(id, key); - ConfiguredObjectBinding configuredBinding = new ConfiguredObjectBinding(); - configuredBinding.objectToEntry(configuredObject, value); - put(configuredObjectsDatabase, transaction, key, value); - } - - private UpgradeConfiguredObjectRecord createQueueConfiguredObjectRecord(String queueName, String owner, boolean exclusive, - FieldTable arguments) - { - Map<String, Object> attributesMap = buildQueueArgumentMap(queueName, - owner, exclusive, arguments); - String json = _serializer.serialize(attributesMap); - UpgradeConfiguredObjectRecord configuredObject = new UpgradeConfiguredObjectRecord(Queue.class.getName(), json); - return configuredObject; - } - - private Map<String, Object> buildQueueArgumentMap(String queueName, - String owner, boolean exclusive, FieldTable arguments) - { - - Map<String, Object> attributesMap = new HashMap<String, Object>(); - attributesMap.put(Queue.NAME, queueName); - attributesMap.put(Queue.EXCLUSIVE, exclusive); - - FieldTable argumentsCopy = new FieldTable(); - if (arguments != null) - { - argumentsCopy.addAll(arguments); - } - - if (moveNonExclusiveOwnerToDescription(owner, exclusive)) - { - _logger.info("Non-exclusive owner " + owner + " for queue " + queueName + " moved to " + QueueArgumentsConverter.X_QPID_DESCRIPTION); - - attributesMap.put(Queue.OWNER, null); - argumentsCopy.put(AMQShortString.valueOf(QueueArgumentsConverter.X_QPID_DESCRIPTION), owner); - } - else - { - attributesMap.put(Queue.OWNER, owner); - } - if (!argumentsCopy.isEmpty()) - { - attributesMap.put(ARGUMENTS, FieldTable.convertToMap(argumentsCopy)); - } - return attributesMap; - } - - private boolean moveNonExclusiveOwnerToDescription(String owner, - boolean exclusive) - { - return exclusive == false && owner != null && _moveNonExclusiveQueueOwnerToDescription; - } - - private UpgradeConfiguredObjectRecord createExchangeConfiguredObjectRecord(String exchangeName, String exchangeType, - boolean autoDelete) - { - Map<String, Object> attributesMap = new HashMap<String, Object>(); - attributesMap.put(Exchange.NAME, exchangeName); - attributesMap.put(Exchange.TYPE, exchangeType); - attributesMap.put(Exchange.LIFETIME_POLICY, autoDelete ? "AUTO_DELETE" - : LifetimePolicy.PERMANENT.name()); - String json = _serializer.serialize(attributesMap); - UpgradeConfiguredObjectRecord configuredObject = new UpgradeConfiguredObjectRecord(Exchange.class.getName(), json); - return configuredObject; - } - - private UpgradeConfiguredObjectRecord createBindingConfiguredObjectRecord(String exchangeName, String queueName, - String routingKey, FieldTable arguments, String virtualHostName) - { - Map<String, Object> attributesMap = new HashMap<String, Object>(); - attributesMap.put(Binding.NAME, routingKey); - attributesMap.put(Binding.EXCHANGE, UUIDGenerator.generateExchangeUUID(exchangeName, virtualHostName)); - attributesMap.put(Binding.QUEUE, UUIDGenerator.generateQueueUUID(queueName, virtualHostName)); - if (arguments != null) - { - attributesMap.put(Binding.ARGUMENTS, FieldTable.convertToMap(arguments)); - } - String json = _serializer.serialize(attributesMap); - UpgradeConfiguredObjectRecord configuredObject = new UpgradeConfiguredObjectRecord(Binding.class.getName(), json); - return configuredObject; - } - - private void put(final Database database, Transaction txn, DatabaseEntry key, DatabaseEntry value) - { - OperationStatus status = database.put(txn, key, value); - if (status != OperationStatus.SUCCESS) - { - throw new StoreException("Cannot add record into " + database.getDatabaseName() + ":" + status); - } - } - - static final class CompoundKey - { - public final long _messageId; - public final int _offset; - - public CompoundKey(final long messageId, final int offset) - { - _messageId = messageId; - _offset = offset; - } - - public long getMessageId() - { - return _messageId; - } - - public int getOffset() - { - return _offset; - } - } - - static final class CompoundKeyBinding extends TupleBinding<CompoundKey> - { - - @Override - public CompoundKey entryToObject(final TupleInput input) - { - return new CompoundKey(input.readLong(), input.readInt()); - } - - @Override - public void objectToEntry(final CompoundKey object, final TupleOutput output) - { - output.writeLong(object._messageId); - output.writeInt(object._offset); - } - } - - static final class OldDataValue - { - private final int _size; - private final byte[] _data; - - private OldDataValue(final int size, final byte[] data) - { - _size = size; - _data = data; - } - - public int getSize() - { - return _size; - } - - public byte[] getData() - { - return _data; - } - } - - static final class OldDataBinding extends TupleBinding<OldDataValue> - { - - @Override - public OldDataValue entryToObject(final TupleInput input) - { - int size = input.readInt(); - byte[] data = new byte[size]; - input.read(data); - return new OldDataValue(size, data); - } - - @Override - public void objectToEntry(OldDataValue value, final TupleOutput output) - { - output.writeInt(value.getSize()); - output.write(value.getData()); - } - } - - static final class NewDataBinding extends TupleBinding<byte[]> - { - - @Override - public byte[] entryToObject(final TupleInput input) - { - byte[] data = new byte[input.available()]; - input.read(data); - return data; - } - - @Override - public void objectToEntry(final byte[] data, final TupleOutput output) - { - output.write(data); - } - } - - static class OldQueueRecord extends Object - { - private final AMQShortString _queueName; - private final AMQShortString _owner; - private final FieldTable _arguments; - private boolean _exclusive; - - public OldQueueRecord(AMQShortString queueName, AMQShortString owner, boolean exclusive, FieldTable arguments) - { - _queueName = queueName; - _owner = owner; - _exclusive = exclusive; - _arguments = arguments; - } - - public AMQShortString getNameShortString() - { - return _queueName; - } - - public AMQShortString getOwner() - { - return _owner; - } - - public boolean isExclusive() - { - return _exclusive; - } - - public void setExclusive(boolean exclusive) - { - _exclusive = exclusive; - } - - public FieldTable getArguments() - { - return _arguments; - } - - } - - static class UpgradeConfiguredObjectRecord - { - private String _attributes; - private String _type; - - public UpgradeConfiguredObjectRecord(String type, String attributes) - { - super(); - _attributes = attributes; - _type = type; - } - - public String getAttributes() - { - return _attributes; - } - - public String getType() - { - return _type; - } - - } - - static class UpgradeQueueBinding extends TupleBinding<OldQueueRecord> - { - public OldQueueRecord entryToObject(TupleInput tupleInput) - { - AMQShortString name = AMQShortStringEncoding.readShortString(tupleInput); - AMQShortString owner = AMQShortStringEncoding.readShortString(tupleInput); - FieldTable arguments = FieldTableEncoding.readFieldTable(tupleInput); - boolean exclusive = tupleInput.readBoolean(); - return new OldQueueRecord(name, owner, exclusive, arguments); - } - - public void objectToEntry(OldQueueRecord queue, TupleOutput tupleOutput) - { - AMQShortStringEncoding.writeShortString(queue.getNameShortString(), tupleOutput); - AMQShortStringEncoding.writeShortString(queue.getOwner(), tupleOutput); - FieldTableEncoding.writeFieldTable(queue.getArguments(), tupleOutput); - tupleOutput.writeBoolean(queue.isExclusive()); - } - } - - static class UpgradeUUIDBinding extends TupleBinding<UUID> - { - public UUID entryToObject(final TupleInput tupleInput) - { - return new UUID(tupleInput.readLong(), tupleInput.readLong()); - } - - public void objectToEntry(final UUID uuid, final TupleOutput tupleOutput) - { - tupleOutput.writeLong(uuid.getMostSignificantBits()); - tupleOutput.writeLong(uuid.getLeastSignificantBits()); - } - } - - static class ConfiguredObjectBinding extends TupleBinding<UpgradeConfiguredObjectRecord> - { - - public UpgradeConfiguredObjectRecord entryToObject(TupleInput tupleInput) - { - String type = tupleInput.readString(); - String json = tupleInput.readString(); - UpgradeConfiguredObjectRecord configuredObject = new UpgradeConfiguredObjectRecord(type, json); - return configuredObject; - } - - public void objectToEntry(UpgradeConfiguredObjectRecord object, TupleOutput tupleOutput) - { - tupleOutput.writeString(object.getType()); - tupleOutput.writeString(object.getAttributes()); - } - - } - - static class ExchangeRecord extends Object - { - private final AMQShortString _exchangeName; - private final AMQShortString _exchangeType; - private final boolean _autoDelete; - - public ExchangeRecord(AMQShortString exchangeName, AMQShortString exchangeType, boolean autoDelete) - { - _exchangeName = exchangeName; - _exchangeType = exchangeType; - _autoDelete = autoDelete; - } - - public AMQShortString getNameShortString() - { - return _exchangeName; - } - - public AMQShortString getType() - { - return _exchangeType; - } - - public boolean isAutoDelete() - { - return _autoDelete; - } - - } - - static class ExchangeBinding extends TupleBinding<ExchangeRecord> - { - - public ExchangeRecord entryToObject(TupleInput tupleInput) - { - AMQShortString name = AMQShortStringEncoding.readShortString(tupleInput); - AMQShortString typeName = AMQShortStringEncoding.readShortString(tupleInput); - - boolean autoDelete = tupleInput.readBoolean(); - - return new ExchangeRecord(name, typeName, autoDelete); - } - - public void objectToEntry(ExchangeRecord exchange, TupleOutput tupleOutput) - { - AMQShortStringEncoding.writeShortString(exchange.getNameShortString(), tupleOutput); - AMQShortStringEncoding.writeShortString(exchange.getType(), tupleOutput); - - tupleOutput.writeBoolean(exchange.isAutoDelete()); - } - } - - static class BindingRecord extends Object - { - private final AMQShortString _exchangeName; - private final AMQShortString _queueName; - private final AMQShortString _routingKey; - private final FieldTable _arguments; - - public BindingRecord(AMQShortString exchangeName, AMQShortString queueName, AMQShortString routingKey, - FieldTable arguments) - { - _exchangeName = exchangeName; - _queueName = queueName; - _routingKey = routingKey; - _arguments = arguments; - } - - public AMQShortString getExchangeName() - { - return _exchangeName; - } - - public AMQShortString getQueueName() - { - return _queueName; - } - - public AMQShortString getRoutingKey() - { - return _routingKey; - } - - public FieldTable getArguments() - { - return _arguments; - } - - } - - static class QueueBindingBinding extends TupleBinding<BindingRecord> - { - - public BindingRecord entryToObject(TupleInput tupleInput) - { - AMQShortString exchangeName = AMQShortStringEncoding.readShortString(tupleInput); - AMQShortString queueName = AMQShortStringEncoding.readShortString(tupleInput); - AMQShortString routingKey = AMQShortStringEncoding.readShortString(tupleInput); - - FieldTable arguments = FieldTableEncoding.readFieldTable(tupleInput); - - return new BindingRecord(exchangeName, queueName, routingKey, arguments); - } - - public void objectToEntry(BindingRecord binding, TupleOutput tupleOutput) - { - AMQShortStringEncoding.writeShortString(binding.getExchangeName(), tupleOutput); - AMQShortStringEncoding.writeShortString(binding.getQueueName(), tupleOutput); - AMQShortStringEncoding.writeShortString(binding.getRoutingKey(), tupleOutput); - - FieldTableEncoding.writeFieldTable(binding.getArguments(), tupleOutput); - } - } - - static class OldQueueEntryKey - { - private AMQShortString _queueName; - private long _messageId; - - public OldQueueEntryKey(AMQShortString queueName, long messageId) - { - _queueName = queueName; - _messageId = messageId; - } - - public AMQShortString getQueueName() - { - return _queueName; - } - - public long getMessageId() - { - return _messageId; - } - } - - static class OldQueueEntryBinding extends TupleBinding<OldQueueEntryKey> - { - - public OldQueueEntryKey entryToObject(TupleInput tupleInput) - { - AMQShortString queueName = AMQShortStringEncoding.readShortString(tupleInput); - long messageId = tupleInput.readLong(); - - return new OldQueueEntryKey(queueName, messageId); - } - - public void objectToEntry(OldQueueEntryKey mk, TupleOutput tupleOutput) - { - AMQShortStringEncoding.writeShortString(mk.getQueueName(), tupleOutput); - tupleOutput.writeLong(mk.getMessageId()); - } - } - - static class NewQueueEntryKey - { - private UUID _queueId; - private long _messageId; - - public NewQueueEntryKey(UUID queueId, long messageId) - { - _queueId = queueId; - _messageId = messageId; - } - - public UUID getQueueId() - { - return _queueId; - } - - public long getMessageId() - { - return _messageId; - } - } - - static class NewQueueEntryBinding extends TupleBinding<NewQueueEntryKey> - { - - public NewQueueEntryKey entryToObject(TupleInput tupleInput) - { - UUID queueId = new UUID(tupleInput.readLong(), tupleInput.readLong()); - long messageId = tupleInput.readLong(); - - return new NewQueueEntryKey(queueId, messageId); - } - - public void objectToEntry(NewQueueEntryKey mk, TupleOutput tupleOutput) - { - UUID uuid = mk.getQueueId(); - tupleOutput.writeLong(uuid.getMostSignificantBits()); - tupleOutput.writeLong(uuid.getLeastSignificantBits()); - tupleOutput.writeLong(mk.getMessageId()); - } - } - - static class NewPreparedTransaction - { - private final NewRecordImpl[] _enqueues; - private final NewRecordImpl[] _dequeues; - - public NewPreparedTransaction(NewRecordImpl[] enqueues, NewRecordImpl[] dequeues) - { - _enqueues = enqueues; - _dequeues = dequeues; - } - - public NewRecordImpl[] getEnqueues() - { - return _enqueues; - } - - public NewRecordImpl[] getDequeues() - { - return _dequeues; - } - } - - static class NewRecordImpl - { - - private long _messageNumber; - private UUID _queueId; - - public NewRecordImpl(UUID queueId, long messageNumber) - { - _messageNumber = messageNumber; - _queueId = queueId; - } - - public long getMessageNumber() - { - return _messageNumber; - } - - public UUID getId() - { - return _queueId; - } - } - - static class NewPreparedTransactionBinding extends TupleBinding<NewPreparedTransaction> - { - @Override - public NewPreparedTransaction entryToObject(TupleInput input) - { - NewRecordImpl[] enqueues = readRecords(input); - - NewRecordImpl[] dequeues = readRecords(input); - - return new NewPreparedTransaction(enqueues, dequeues); - } - - private NewRecordImpl[] readRecords(TupleInput input) - { - NewRecordImpl[] records = new NewRecordImpl[input.readInt()]; - for (int i = 0; i < records.length; i++) - { - records[i] = new NewRecordImpl(new UUID(input.readLong(), input.readLong()), input.readLong()); - } - return records; - } - - @Override - public void objectToEntry(NewPreparedTransaction preparedTransaction, TupleOutput output) - { - writeRecords(preparedTransaction.getEnqueues(), output); - writeRecords(preparedTransaction.getDequeues(), output); - } - - private void writeRecords(NewRecordImpl[] records, TupleOutput output) - { - if (records == null) - { - output.writeInt(0); - } - else - { - output.writeInt(records.length); - for (NewRecordImpl record : records) - { - UUID id = record.getId(); - output.writeLong(id.getMostSignificantBits()); - output.writeLong(id.getLeastSignificantBits()); - output.writeLong(record.getMessageNumber()); - } - } - } - } - - static class OldRecordImpl - { - - private long _messageNumber; - private String _queueName; - - public OldRecordImpl(String queueName, long messageNumber) - { - _messageNumber = messageNumber; - _queueName = queueName; - } - - public long getMessageNumber() - { - return _messageNumber; - } - - public String getQueueName() - { - return _queueName; - } - } - - static class OldPreparedTransaction - { - private final OldRecordImpl[] _enqueues; - private final OldRecordImpl[] _dequeues; - - public OldPreparedTransaction(OldRecordImpl[] enqueues, OldRecordImpl[] dequeues) - { - _enqueues = enqueues; - _dequeues = dequeues; - } - - public OldRecordImpl[] getEnqueues() - { - return _enqueues; - } - - public OldRecordImpl[] getDequeues() - { - return _dequeues; - } - } - - static class OldPreparedTransactionBinding extends TupleBinding<OldPreparedTransaction> - { - @Override - public OldPreparedTransaction entryToObject(TupleInput input) - { - OldRecordImpl[] enqueues = readRecords(input); - - OldRecordImpl[] dequeues = readRecords(input); - - return new OldPreparedTransaction(enqueues, dequeues); - } - - private OldRecordImpl[] readRecords(TupleInput input) - { - OldRecordImpl[] records = new OldRecordImpl[input.readInt()]; - for (int i = 0; i < records.length; i++) - { - records[i] = new OldRecordImpl(input.readString(), input.readLong()); - } - return records; - } - - @Override - public void objectToEntry(OldPreparedTransaction preparedTransaction, TupleOutput output) - { - writeRecords(preparedTransaction.getEnqueues(), output); - writeRecords(preparedTransaction.getDequeues(), output); - } - - private void writeRecords(OldRecordImpl[] records, TupleOutput output) - { - if (records == null) - { - output.writeInt(0); - } - else - { - output.writeInt(records.length); - for (OldRecordImpl record : records) - { - output.writeString(record.getQueueName()); - output.writeLong(record.getMessageNumber()); - } - } - } - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom6To7.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom6To7.java deleted file mode 100644 index 9dcd291b9d..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom6To7.java +++ /dev/null @@ -1,66 +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.upgrade; - -import com.sleepycat.bind.tuple.ByteBinding; -import com.sleepycat.bind.tuple.IntegerBinding; -import com.sleepycat.je.Database; -import com.sleepycat.je.DatabaseConfig; -import com.sleepycat.je.DatabaseEntry; -import com.sleepycat.je.Environment; -import com.sleepycat.je.OperationStatus; - -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.store.StoreException; - -public class UpgradeFrom6To7 extends AbstractStoreUpgrade -{ - - private static final int DEFAULT_CONFIG_VERSION = 0; - - @Override - public void performUpgrade(Environment environment, UpgradeInteractionHandler handler, ConfiguredObject<?> parent) - { - reportStarting(environment, 6); - DatabaseConfig dbConfig = new DatabaseConfig(); - dbConfig.setTransactional(true); - dbConfig.setAllowCreate(true); - - Database versionDb = environment.openDatabase(null, "CONFIG_VERSION", dbConfig); - - if(versionDb.count() == 0L) - { - DatabaseEntry key = new DatabaseEntry(); - DatabaseEntry value = new DatabaseEntry(); - IntegerBinding.intToEntry(DEFAULT_CONFIG_VERSION, value); - ByteBinding.byteToEntry((byte) 0, key); - OperationStatus status = versionDb.put(null, key, value); - if (status != OperationStatus.SUCCESS) - { - throw new StoreException("Error initialising config version: " + status); - } - } - - versionDb.close(); - - reportFinished(environment, 7); - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom7To8.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom7To8.java deleted file mode 100644 index 4638194970..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom7To8.java +++ /dev/null @@ -1,311 +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.upgrade; - -import java.io.IOException; -import java.io.StringWriter; -import java.nio.charset.Charset; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import org.apache.qpid.server.model.BrokerModel; -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.store.ConfiguredObjectRecord; -import org.apache.qpid.server.store.StoreException; -import org.apache.qpid.server.store.berkeleydb.tuple.ConfiguredObjectBinding; -import org.apache.qpid.server.store.berkeleydb.tuple.MessageMetaDataBinding; -import org.apache.qpid.server.store.berkeleydb.tuple.UUIDTupleBinding; - -import com.sleepycat.bind.tuple.LongBinding; -import com.sleepycat.je.Sequence; -import com.sleepycat.je.SequenceConfig; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; - -import com.sleepycat.bind.tuple.IntegerBinding; -import com.sleepycat.bind.tuple.TupleBinding; -import com.sleepycat.bind.tuple.TupleInput; -import com.sleepycat.bind.tuple.TupleOutput; -import com.sleepycat.je.Cursor; -import com.sleepycat.je.Database; -import com.sleepycat.je.DatabaseConfig; -import com.sleepycat.je.DatabaseEntry; -import com.sleepycat.je.Environment; -import com.sleepycat.je.LockMode; -import com.sleepycat.je.OperationStatus; -import com.sleepycat.je.Transaction; - -public class UpgradeFrom7To8 extends AbstractStoreUpgrade -{ - private static final TypeReference<HashMap<String, Object>> MAP_TYPE_REFERENCE = new TypeReference<HashMap<String,Object>>(){}; - - @SuppressWarnings("serial") - private Map<String, String> _defaultExchanges = new HashMap<String, String>() - {{ - put("amq.direct", "direct"); - put("amq.topic", "topic"); - put("amq.fanout", "fanout"); - put("amq.match", "headers"); - }}; - - private static final DatabaseEntry MESSAGE_METADATA_SEQ_KEY = new DatabaseEntry("MESSAGE_METADATA_SEQ_KEY".getBytes(Charset.forName("UTF-8"))); - private static SequenceConfig MESSAGE_METADATA_SEQ_CONFIG = SequenceConfig.DEFAULT. - setAllowCreate(true). - setWrap(true). - setCacheSize(100000); - - @Override - public void performUpgrade(Environment environment, UpgradeInteractionHandler handler, ConfiguredObject<?> parent) - { - reportStarting(environment, 7); - - DatabaseConfig dbConfig = new DatabaseConfig(); - dbConfig.setTransactional(true); - dbConfig.setAllowCreate(true); - - Database hierarchyDb = environment.openDatabase(null, "CONFIGURED_OBJECT_HIERARCHY", dbConfig); - Database configuredObjectsDb = environment.openDatabase(null, "CONFIGURED_OBJECTS", dbConfig); - Database configVersionDb = environment.openDatabase(null, "CONFIG_VERSION", dbConfig); - Database messageMetadataDb = environment.openDatabase(null, "MESSAGE_METADATA", dbConfig); - Database messageMetadataSeqDb = environment.openDatabase(null, "MESSAGE_METADATA.SEQ", dbConfig); - - long maxMessageId = getMaximumMessageId(messageMetadataDb); - createMessageMetadataSequence(messageMetadataSeqDb, maxMessageId); - - Cursor objectsCursor = null; - - String stringifiedConfigVersion = BrokerModel.MODEL_VERSION; - int configVersion = getConfigVersion(configVersionDb); - if (configVersion > -1) - { - stringifiedConfigVersion = "0." + configVersion; - } - configVersionDb.close(); - - String virtualHostName = parent.getName(); - Map<String, Object> virtualHostAttributes = new HashMap<String, Object>(); - virtualHostAttributes.put("modelVersion", stringifiedConfigVersion); - virtualHostAttributes.put("name", virtualHostName); - UUID virtualHostId = UUIDGenerator.generateVhostUUID(virtualHostName); - ConfiguredObjectRecord virtualHostRecord = new org.apache.qpid.server.store.ConfiguredObjectRecordImpl(virtualHostId, "VirtualHost", virtualHostAttributes); - - Transaction txn = environment.beginTransaction(null, null); - - try - { - objectsCursor = configuredObjectsDb.openCursor(txn, null); - DatabaseEntry key = new DatabaseEntry(); - DatabaseEntry value = new DatabaseEntry(); - ObjectMapper mapper = new ObjectMapper(); - - while (objectsCursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) - { - UUID id = UUIDTupleBinding.getInstance().entryToObject(key); - TupleInput input = TupleBinding.entryToInput(value); - String type = input.readString(); - String json = input.readString(); - Map<String,Object> attributes = null; - try - { - attributes = mapper.readValue(json, MAP_TYPE_REFERENCE); - } - catch (Exception e) - { - throw new StoreException(e); - } - String name = (String)attributes.get("name"); - - if (type.equals("Exchange")) - { - _defaultExchanges.remove(name); - } - - if(!type.endsWith("Binding")) - { - storeVirtualHostHierarchyRecord(hierarchyDb, txn, id, virtualHostId); - } - else - { - try - { - DatabaseEntry hierarchyKey = new DatabaseEntry(); - DatabaseEntry hierarchyValue = new DatabaseEntry(); - - Object queueIdString = attributes.remove("queue"); - if(queueIdString instanceof String) - { - UUID queueId = UUID.fromString(queueIdString.toString()); - UUIDTupleBinding.getInstance().objectToEntry(queueId,hierarchyValue); - TupleOutput tupleOutput = new TupleOutput(); - tupleOutput.writeLong(id.getMostSignificantBits()); - tupleOutput.writeLong(id.getLeastSignificantBits()); - tupleOutput.writeString("Queue"); - TupleBinding.outputToEntry(tupleOutput, hierarchyKey); - hierarchyDb.put(txn, hierarchyKey, hierarchyValue); - } - Object exchangeIdString = attributes.remove("exchange"); - if(exchangeIdString instanceof String) - { - UUID exchangeId = UUID.fromString(exchangeIdString.toString()); - UUIDTupleBinding.getInstance().objectToEntry(exchangeId,hierarchyValue); - TupleOutput tupleOutput = new TupleOutput(); - tupleOutput.writeLong(id.getMostSignificantBits()); - tupleOutput.writeLong(id.getLeastSignificantBits()); - tupleOutput.writeString("Exchange"); - TupleBinding.outputToEntry(tupleOutput, hierarchyKey); - hierarchyDb.put(txn, hierarchyKey, hierarchyValue); - } - TupleOutput tupleOutput = new TupleOutput(); - tupleOutput.writeString(type); - StringWriter writer = new StringWriter(); - mapper.writeValue(writer,attributes); - tupleOutput.writeString(writer.getBuffer().toString()); - TupleBinding.outputToEntry(tupleOutput, value); - objectsCursor.putCurrent(value); - } - catch (IOException e) - { - throw new StoreException(e); - } - } - } - } - finally - { - if(objectsCursor != null) - { - objectsCursor.close(); - } - } - - storeConfiguredObjectEntry(configuredObjectsDb, txn, virtualHostRecord); - for (Map.Entry<String, String> defaultExchangeEntry : _defaultExchanges.entrySet()) - { - UUID id = UUIDGenerator.generateExchangeUUID(defaultExchangeEntry.getKey(), virtualHostName); - Map<String, Object> exchangeAttributes = new HashMap<String, Object>(); - exchangeAttributes.put("name", defaultExchangeEntry.getKey()); - exchangeAttributes.put("type", defaultExchangeEntry.getValue()); - exchangeAttributes.put("lifetimePolicy", "PERMANENT"); - ConfiguredObjectRecord exchangeRecord = new org.apache.qpid.server.store.ConfiguredObjectRecordImpl(id, "Exchange", exchangeAttributes); - storeConfiguredObjectEntry(configuredObjectsDb, txn, exchangeRecord); - storeVirtualHostHierarchyRecord(hierarchyDb, txn, id, virtualHostId); - } - txn.commit(); - - hierarchyDb.close(); - configuredObjectsDb.close(); - messageMetadataDb.close(); - messageMetadataSeqDb.close(); - - reportFinished(environment, 8); - } - - void storeVirtualHostHierarchyRecord(Database hierarchyDb, Transaction txn, UUID id, UUID virtualHostId) - { - DatabaseEntry key = new DatabaseEntry(); - DatabaseEntry value = new DatabaseEntry(); - UUIDTupleBinding.getInstance().objectToEntry(virtualHostId, value); - TupleOutput tupleOutput = new TupleOutput(); - tupleOutput.writeLong(id.getMostSignificantBits()); - tupleOutput.writeLong(id.getLeastSignificantBits()); - tupleOutput.writeString("VirtualHost"); - TupleBinding.outputToEntry(tupleOutput, key); - hierarchyDb.put(txn, key, value); - } - - private void createMessageMetadataSequence(final Database messageMetadataSeqDb, - final long maximumMessageId) - { - SequenceConfig sequenceConfig = MESSAGE_METADATA_SEQ_CONFIG.setInitialValue(maximumMessageId + 1); - - Sequence messageMetadataSeq = messageMetadataSeqDb.openSequence(null, MESSAGE_METADATA_SEQ_KEY, sequenceConfig); - messageMetadataSeq.close(); - } - - private int getConfigVersion(Database configVersionDb) - { - 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); - } - return -1; - } - finally - { - cursor.close(); - } - } - - private void storeConfiguredObjectEntry(Database configuredObjectsDb, final Transaction txn, ConfiguredObjectRecord configuredObject) - { - DatabaseEntry key = new DatabaseEntry(); - UUIDTupleBinding uuidBinding = UUIDTupleBinding.getInstance(); - uuidBinding.objectToEntry(configuredObject.getId(), key); - - DatabaseEntry value = new DatabaseEntry(); - ConfiguredObjectBinding configuredObjectBinding = ConfiguredObjectBinding.getInstance(); - - configuredObjectBinding.objectToEntry(configuredObject, value); - OperationStatus status = configuredObjectsDb.put(txn, key, value); - if (status != OperationStatus.SUCCESS) - { - throw new StoreException("Error writing configured object " + configuredObject + " to database: " - + status); - } - } - - private long getMaximumMessageId(Database messageMetaDataDb) - { - Cursor cursor = null; - long maximumMessageId = 0; // Our hand-rolled sequences value always began at zero - try - { - cursor = messageMetaDataDb.openCursor(null, null); - DatabaseEntry key = new DatabaseEntry(); - DatabaseEntry value = new DatabaseEntry(); - MessageMetaDataBinding valueBinding = MessageMetaDataBinding.getInstance(); - - while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) - { - long messageId = LongBinding.entryToLong(key); - maximumMessageId = Math.max(messageId, maximumMessageId); - } - } - finally - { - if (cursor != null) - { - cursor.close(); - } - } - - return maximumMessageId; - } - -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeInteractionHandler.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeInteractionHandler.java deleted file mode 100644 index 0cedbd15e0..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeInteractionHandler.java +++ /dev/null @@ -1,37 +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.upgrade; - -public interface UpgradeInteractionHandler -{ - UpgradeInteractionResponse requireResponse(String question, UpgradeInteractionResponse defaultResponse, - UpgradeInteractionResponse... possibleResponses); - - public static final UpgradeInteractionHandler DEFAULT_HANDLER = new UpgradeInteractionHandler() - { - public UpgradeInteractionResponse requireResponse(final String question, - final UpgradeInteractionResponse defaultResponse, - final UpgradeInteractionResponse... possibleResponses) - { - return defaultResponse; - } - }; -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeInteractionResponse.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeInteractionResponse.java deleted file mode 100644 index eb5a049a9a..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeInteractionResponse.java +++ /dev/null @@ -1,28 +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.upgrade; - -public enum UpgradeInteractionResponse -{ - YES, - NO, - ABORT -} 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 deleted file mode 100644 index ec22ad0fc8..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/Upgrader.java +++ /dev/null @@ -1,209 +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.upgrade; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; - -import com.sleepycat.bind.tuple.IntegerBinding; -import com.sleepycat.bind.tuple.LongBinding; -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.OperationStatus; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.store.StoreException; -import org.apache.qpid.server.store.berkeleydb.BDBConfigurationStore; - -public class Upgrader -{ - private static final Logger LOGGER = LoggerFactory.getLogger(Upgrader.class); - - static final String VERSION_DB_NAME = "DB_VERSION"; - - private Environment _environment; - private ConfiguredObject<?> _parent; - - public Upgrader(Environment environment, ConfiguredObject<?> parent) - { - _environment = environment; - _parent = parent; - } - - public void upgradeIfNecessary() - { - boolean isEmpty = _environment.getDatabaseNames().isEmpty(); - DatabaseConfig dbConfig = new DatabaseConfig(); - dbConfig.setTransactional(true); - dbConfig.setAllowCreate(true); - - Database versionDb = null; - try - { - versionDb = _environment.openDatabase(null, VERSION_DB_NAME, dbConfig); - - if(versionDb.count() == 0L) - { - - int sourceVersion = isEmpty ? BDBConfigurationStore.VERSION: identifyOldStoreVersion(); - DatabaseEntry key = new DatabaseEntry(); - IntegerBinding.intToEntry(sourceVersion, key); - DatabaseEntry value = new DatabaseEntry(); - LongBinding.longToEntry(System.currentTimeMillis(), value); - - versionDb.put(null, key, value); - } - - int version = getSourceVersion(versionDb); - - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Source message store version is " + version); - } - - if(version > BDBConfigurationStore.VERSION) - { - throw new StoreException("Database version " + version - + " is higher than the most recent known version: " - + BDBConfigurationStore.VERSION); - } - performUpgradeFromVersion(version, versionDb); - } - finally - { - if (versionDb != null) - { - versionDb.close(); - } - } - } - - int getSourceVersion(Database versionDb) - { - int version = -1; - - Cursor cursor = null; - try - { - cursor = versionDb.openCursor(null, null); - - DatabaseEntry key = new DatabaseEntry(); - DatabaseEntry value = new DatabaseEntry(); - - while(cursor.getNext(key, value, null) == OperationStatus.SUCCESS) - { - int ver = IntegerBinding.entryToInt(key); - if(ver > version) - { - version = ver; - } - } - } - finally - { - if(cursor != null) - { - cursor.close(); - } - } - - - return version; - } - - void performUpgradeFromVersion(int sourceVersion, Database versionDb) - throws StoreException - { - while(sourceVersion != BDBConfigurationStore.VERSION) - { - upgrade(sourceVersion, ++sourceVersion); - DatabaseEntry key = new DatabaseEntry(); - IntegerBinding.intToEntry(sourceVersion, key); - DatabaseEntry value = new DatabaseEntry(); - LongBinding.longToEntry(System.currentTimeMillis(), value); - versionDb.put(null, key, value); - } - } - - void upgrade(final int fromVersion, final int toVersion) throws StoreException - { - try - { - @SuppressWarnings("unchecked") - Class<StoreUpgrade> upgradeClass = - (Class<StoreUpgrade>) Class.forName("org.apache.qpid.server.store.berkeleydb.upgrade." - + "UpgradeFrom"+fromVersion+"To"+toVersion); - Constructor<StoreUpgrade> ctr = upgradeClass.getConstructor(); - StoreUpgrade upgrade = ctr.newInstance(); - upgrade.performUpgrade(_environment, UpgradeInteractionHandler.DEFAULT_HANDLER, _parent); - } - catch (ClassNotFoundException e) - { - throw new StoreException("Unable to upgrade BDB data store from version " + fromVersion + " to version" - + toVersion, e); - } - catch (NoSuchMethodException e) - { - throw new StoreException("Unable to upgrade BDB data store from version " + fromVersion + " to version" - + toVersion, e); - } - catch (InvocationTargetException e) - { - throw new StoreException("Unable to upgrade BDB data store from version " + fromVersion + " to version" - + toVersion, e); - } - catch (InstantiationException e) - { - throw new StoreException("Unable to upgrade BDB data store from version " + fromVersion + " to version" - + toVersion, e); - } - catch (IllegalAccessException e) - { - throw new StoreException("Unable to upgrade BDB data store from version " + fromVersion + " to version" - + toVersion, e); - } - } - - private int identifyOldStoreVersion() throws DatabaseException - { - int version = BDBConfigurationStore.VERSION; - for (String databaseName : _environment.getDatabaseNames()) - { - if (databaseName.contains("_v")) - { - int versionIndex = databaseName.indexOf("_v"); - if (versionIndex == -1) - { - versionIndex = 1; - } - version = Integer.parseInt(databaseName.substring(versionIndex + 2)); - break; - } - } - return version; - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAReplicaVirtualHost.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAReplicaVirtualHost.java deleted file mode 100644 index 6fdee4449e..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAReplicaVirtualHost.java +++ /dev/null @@ -1,35 +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.virtualhost.berkeleydb; - -import org.apache.qpid.server.exchange.ExchangeImpl; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.virtualhost.NonStandardVirtualHost; -import org.apache.qpid.server.virtualhost.VirtualHostImpl; - -/** - Object that represents the VirtualHost whilst the VirtualHostNode is in the replica role. The - real virtualhost will be elsewhere in the group. - */ -public interface BDBHAReplicaVirtualHost<X extends BDBHAReplicaVirtualHost<X>> - extends VirtualHostImpl<X, AMQQueue<?>, ExchangeImpl<?>>, - NonStandardVirtualHost<X,AMQQueue<?>,ExchangeImpl<?>> -{ -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAReplicaVirtualHostImpl.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAReplicaVirtualHostImpl.java deleted file mode 100644 index f68532b1d8..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAReplicaVirtualHostImpl.java +++ /dev/null @@ -1,525 +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.virtualhost.berkeleydb; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ScheduledFuture; - -import com.google.common.util.concurrent.ListenableFuture; - -import org.apache.qpid.server.connection.IConnectionRegistry; -import org.apache.qpid.server.exchange.ExchangeImpl; -import org.apache.qpid.server.logging.EventLogger; -import org.apache.qpid.server.message.MessageDestination; -import org.apache.qpid.server.message.MessageSource; -import org.apache.qpid.server.model.AbstractConfiguredObject; -import org.apache.qpid.server.model.BrokerModel; -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.ManagedAttributeField; -import org.apache.qpid.server.model.ManagedObject; -import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; -import org.apache.qpid.server.model.State; -import org.apache.qpid.server.model.VirtualHostAlias; -import org.apache.qpid.server.model.VirtualHostNode; -import org.apache.qpid.server.model.port.AmqpPort; -import org.apache.qpid.server.protocol.AMQConnectionModel; -import org.apache.qpid.server.protocol.LinkRegistry; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.stats.StatisticsCounter; -import org.apache.qpid.server.store.DurableConfigurationStore; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.txn.DtxRegistry; -import org.apache.qpid.server.virtualhost.ExchangeIsAlternateException; -import org.apache.qpid.server.virtualhost.HouseKeepingTask; -import org.apache.qpid.server.virtualhost.RequiredExchangeException; - -/** - Object that represents the VirtualHost whilst the VirtualHostNode is in the replica role. The - real virtualhost will be elsewhere in the group. - */ -@ManagedObject( category = false, type = "BDB_HA_REPLICA", register = false ) -public class BDBHAReplicaVirtualHostImpl extends AbstractConfiguredObject<BDBHAReplicaVirtualHostImpl> implements BDBHAReplicaVirtualHost<BDBHAReplicaVirtualHostImpl> -{ - private final StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived; - - @ManagedAttributeField - private boolean _queue_deadLetterQueueEnabled; - - @ManagedAttributeField - private long _housekeepingCheckPeriod; - - @ManagedAttributeField - private long _storeTransactionIdleTimeoutClose; - - @ManagedAttributeField - private long _storeTransactionIdleTimeoutWarn; - - @ManagedAttributeField - private long _storeTransactionOpenTimeoutClose; - - @ManagedAttributeField - private long _storeTransactionOpenTimeoutWarn; - @ManagedAttributeField - private int _housekeepingThreadCount; - - @ManagedAttributeField - private List<String> _enabledConnectionValidators; - - @ManagedAttributeField - private List<String> _disabledConnectionValidators; - - @ManagedAttributeField - private List<String> _globalAddressDomains; - - @ManagedObjectFactoryConstructor - public BDBHAReplicaVirtualHostImpl(final Map<String, Object> attributes, VirtualHostNode<?> virtualHostNode) - { - super(parentsMap(virtualHostNode), attributes); - - _messagesDelivered = new StatisticsCounter("messages-delivered-" + getName()); - _dataDelivered = new StatisticsCounter("bytes-delivered-" + getName()); - _messagesReceived = new StatisticsCounter("messages-received-" + getName()); - _dataReceived = new StatisticsCounter("bytes-received-" + getName()); - setState(State.UNAVAILABLE); - } - - @Override - protected void validateChange(final ConfiguredObject<?> proxyForValidation, final Set<String> changedAttributes) - { - super.validateChange(proxyForValidation, changedAttributes); - - throwUnsupportedForReplica(); - } - - @Override - public String getModelVersion() - { - return BrokerModel.MODEL_VERSION; - } - - @Override - protected <C extends ConfiguredObject> ListenableFuture<C> addChildAsync(final Class<C> childClass, - final Map<String, Object> attributes, - final ConfiguredObject... otherParents) - { - throwUnsupportedForReplica(); - return null; - } - - @Override - public ExchangeImpl createExchange(final Map<String, Object> attributes) - { - throwUnsupportedForReplica(); - return null; - } - - @Override - public void removeExchange(final ExchangeImpl<?> exchange, final boolean force) - throws ExchangeIsAlternateException, RequiredExchangeException - { - throwUnsupportedForReplica(); - } - - @Override - public MessageDestination getMessageDestination(final String name) - { - return null; - } - - @Override - public ExchangeImpl<?> getExchange(final String name) - { - return null; - } - - @Override - public AMQQueue<?> createQueue(final Map<String, Object> attributes) - { - throwUnsupportedForReplica(); - return null; - } - - @Override - public void executeTransaction(final TransactionalOperation op) - { - throwUnsupportedForReplica(); - } - - @Override - public Collection<String> getExchangeTypeNames() - { - return getObjectFactory().getSupportedTypes(Exchange.class); - } - - @Override - public String getRedirectHost(final AmqpPort<?> port) - { - return null; - } - - @Override - public boolean isQueue_deadLetterQueueEnabled() - { - return false; - } - - @Override - public long getHousekeepingCheckPeriod() - { - return 0; - } - - @Override - public long getStoreTransactionIdleTimeoutClose() - { - return 0; - } - - @Override - public long getStoreTransactionIdleTimeoutWarn() - { - return 0; - } - - @Override - public long getStoreTransactionOpenTimeoutClose() - { - return 0; - } - - @Override - public long getStoreTransactionOpenTimeoutWarn() - { - return 0; - } - - @Override - public int getHousekeepingThreadCount() - { - return 0; - } - - @Override - public long getQueueCount() - { - return 0; - } - - @Override - public long getExchangeCount() - { - return 0; - } - - @Override - public long getConnectionCount() - { - return 0; - } - - @Override - public long getBytesIn() - { - return 0; - } - - @Override - public long getBytesOut() - { - return 0; - } - - @Override - public long getMessagesIn() - { - return 0; - } - - @Override - public long getMessagesOut() - { - return 0; - } - - @Override - public Collection<VirtualHostAlias> getAliases() - { - return Collections.emptyList(); - } - - @Override - public Collection<Connection> getConnections() - { - return Collections.emptyList(); - } - - @Override - public IConnectionRegistry getConnectionRegistry() - { - return null; - } - - @Override - public AMQQueue<?> getQueue(final String name) - { - return null; - } - - @Override - public MessageSource getMessageSource(final String name) - { - return null; - } - - @Override - public AMQQueue<?> getQueue(final UUID id) - { - return null; - } - - @Override - public Collection<AMQQueue<?>> getQueues() - { - return Collections.emptyList(); - } - - @Override - public int removeQueue(final AMQQueue<?> queue) - { - throwUnsupportedForReplica(); - return 0; - } - - @Override - public Collection<ExchangeImpl<?>> getExchanges() - { - return Collections.emptyList(); - } - - @Override - public DurableConfigurationStore getDurableConfigurationStore() - { - return null; - } - - @Override - public ExchangeImpl<?> getExchange(final UUID id) - { - return null; - } - - @Override - public MessageDestination getDefaultDestination() - { - return null; - } - - @Override - public MessageStore getMessageStore() - { - return null; - } - - @Override - public void setTargetSize(final long targetSize) - { - - } - - @Override - public long getTargetSize() - { - return 0l; - } - - @Override - public long getTotalQueueDepthBytes() - { - return 0l; - } - - @Override - public SecurityManager getSecurityManager() - { - return super.getSecurityManager(); - } - - @Override - public void scheduleHouseKeepingTask(final long period, final HouseKeepingTask task) - { - } - - @Override - public long getHouseKeepingTaskCount() - { - return 0; - } - - @Override - public long getHouseKeepingCompletedTaskCount() - { - return 0; - } - - @Override - public int getHouseKeepingPoolSize() - { - return 0; - } - - @Override - public void setHouseKeepingPoolSize(final int newSize) - { - } - - @Override - public int getHouseKeepingActiveCount() - { - return 0; - } - - @Override - public DtxRegistry getDtxRegistry() - { - return null; - } - - @Override - public LinkRegistry getLinkRegistry(final String remoteContainerId) - { - return null; - } - - @Override - public ScheduledFuture<?> scheduleTask(final long delay, final Runnable timeoutTask) - { - throwUnsupportedForReplica(); - return null; - } - - @Override - public boolean getDefaultDeadLetterQueueEnabled() - { - return false; - } - - @Override - public EventLogger getEventLogger() - { - return null; - } - - @Override - public void registerMessageReceived(final long messageSize, final long timestamp) - { - throwUnsupportedForReplica(); - } - - @Override - public void registerMessageDelivered(final long messageSize) - { - throwUnsupportedForReplica(); - } - - @Override - public StatisticsCounter getMessageDeliveryStatistics() - { - return _messagesDelivered; - } - - @Override - public StatisticsCounter getMessageReceiptStatistics() - { - return _messagesReceived; - } - - @Override - public StatisticsCounter getDataDeliveryStatistics() - { - return _dataDelivered; - } - - @Override - public StatisticsCounter getDataReceiptStatistics() - { - return _dataReceived; - } - - @Override - public void resetStatistics() - { - } - - @Override - public boolean authoriseCreateConnection(final AMQConnectionModel<?, ?> connection) - { - return false; - } - - @Override - public List<String> getEnabledConnectionValidators() - { - return _enabledConnectionValidators; - } - - @Override - public List<String> getDisabledConnectionValidators() - { - return _disabledConnectionValidators; - } - - @Override - public List<String> getGlobalAddressDomains() - { - return _globalAddressDomains; - } - - @Override - public String getLocalAddress(final String routingAddress) - { - String localAddress = routingAddress; - if(getGlobalAddressDomains() != null) - { - for(String domain : getGlobalAddressDomains()) - { - if(localAddress.length() > routingAddress.length() - domain.length() && routingAddress.startsWith(domain + "/")) - { - localAddress = routingAddress.substring(domain.length()); - } - } - } - return localAddress; - } - - private void throwUnsupportedForReplica() - { - throw new IllegalStateException("The virtual host state of " + getState() - + " does not permit this operation."); - } - -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAVirtualHost.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAVirtualHost.java deleted file mode 100644 index 2f31384f98..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAVirtualHost.java +++ /dev/null @@ -1,59 +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.virtualhost.berkeleydb; - -import org.apache.qpid.server.exchange.ExchangeImpl; -import org.apache.qpid.server.model.DerivedAttribute; -import org.apache.qpid.server.model.ManagedAttribute; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.store.SizeMonitoringSettings; -import org.apache.qpid.server.virtualhost.NonStandardVirtualHost; -import org.apache.qpid.server.virtualhost.VirtualHostImpl; - -public interface BDBHAVirtualHost<X extends BDBHAVirtualHost<X>> - extends VirtualHostImpl<X, AMQQueue<?>, ExchangeImpl<?>>, - SizeMonitoringSettings, - NonStandardVirtualHost<X,AMQQueue<?>,ExchangeImpl<?>> -{ - String REMOTE_TRANSACTION_SYNCHRONIZATION_POLICY = "remoteTransactionSynchronizationPolicy"; - String LOCAL_TRANSACTION_SYNCHRONIZATION_POLICY = "localTransactionSynchronizationPolicy"; - String COALESCING_SYNC = "coalescingSync"; - String DURABILITY = "durability"; - String STORE_PATH = "storePath"; - - @ManagedAttribute( defaultValue = "SYNC") - String getLocalTransactionSynchronizationPolicy(); - - @ManagedAttribute( defaultValue = "NO_SYNC") - String getRemoteTransactionSynchronizationPolicy(); - - @DerivedAttribute - boolean isCoalescingSync(); - - @DerivedAttribute - String getDurability(); - - @ManagedAttribute(mandatory = true, defaultValue = "0") - Long getStoreUnderfullSize(); - - @ManagedAttribute(mandatory = true, defaultValue = "0") - Long getStoreOverfullSize(); -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAVirtualHostImpl.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAVirtualHostImpl.java deleted file mode 100644 index 21cee14fa7..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAVirtualHostImpl.java +++ /dev/null @@ -1,171 +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.virtualhost.berkeleydb; - -import java.util.Map; -import java.util.Set; - -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.model.ManagedAttributeField; -import org.apache.qpid.server.model.ManagedObject; -import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; -import org.apache.qpid.server.model.VirtualHostNode; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.berkeleydb.BDBConfigurationStore; -import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacade; -import org.apache.qpid.server.virtualhost.AbstractVirtualHost; - -import com.sleepycat.je.Durability.SyncPolicy; - -@ManagedObject( category = false, type = BDBHAVirtualHostImpl.VIRTUAL_HOST_TYPE ) -public class BDBHAVirtualHostImpl extends AbstractVirtualHost<BDBHAVirtualHostImpl> implements BDBHAVirtualHost<BDBHAVirtualHostImpl> -{ - public static final String VIRTUAL_HOST_TYPE = "BDB_HA"; - - private final BDBConfigurationStore _configurationStore; - - @ManagedAttributeField - private String _localTransactionSynchronizationPolicy; - - @ManagedAttributeField - private String _remoteTransactionSynchronizationPolicy; - - @ManagedAttributeField - private Long _storeUnderfullSize; - - @ManagedAttributeField - private Long _storeOverfullSize; - - @ManagedObjectFactoryConstructor - public BDBHAVirtualHostImpl(final Map<String, Object> attributes, VirtualHostNode<?> virtualHostNode) - { - super(attributes, virtualHostNode); - - _configurationStore = (BDBConfigurationStore) virtualHostNode.getConfigurationStore(); - } - - @Override - protected MessageStore createMessageStore() - { - return _configurationStore.getMessageStore(); - } - - @Override - public String getLocalTransactionSynchronizationPolicy() - { - return _localTransactionSynchronizationPolicy; - } - - @Override - public String getRemoteTransactionSynchronizationPolicy() - { - return _remoteTransactionSynchronizationPolicy; - } - - @Override - public String getDurability() - { - ReplicatedEnvironmentFacade facade = getReplicatedEnvironmentFacade(); - if (facade != null) - { - return String.valueOf(facade.getMessageStoreDurability()); - } - return null; - } - - @Override - public boolean isCoalescingSync() - { - return SyncPolicy.SYNC.name().equals(_localTransactionSynchronizationPolicy); - } - - @Override - public void onOpen() - { - ReplicatedEnvironmentFacade facade = getReplicatedEnvironmentFacade(); - if (facade != null) - { - facade.setMessageStoreDurability( - SyncPolicy.valueOf(getLocalTransactionSynchronizationPolicy()), - SyncPolicy.valueOf(getRemoteTransactionSynchronizationPolicy()), - ReplicatedEnvironmentFacade.REPLICA_REPLICA_ACKNOWLEDGMENT_POLICY); - } - super.onOpen(); - } - - @Override - protected void validateChange(final ConfiguredObject<?> proxyForValidation, final Set<String> changedAttributes) - { - super.validateChange(proxyForValidation, changedAttributes); - - if(changedAttributes.contains(LOCAL_TRANSACTION_SYNCHRONIZATION_POLICY)) - { - String policy = ((BDBHAVirtualHost<?>)proxyForValidation).getLocalTransactionSynchronizationPolicy(); - validateTransactionSynchronizationPolicy(policy); - } - - if(changedAttributes.contains(REMOTE_TRANSACTION_SYNCHRONIZATION_POLICY)) - { - String policy = ((BDBHAVirtualHost<?>)proxyForValidation).getRemoteTransactionSynchronizationPolicy(); - validateTransactionSynchronizationPolicy(policy); - } - - } - - private void validateTransactionSynchronizationPolicy(String policy) - { - try - { - SyncPolicy.valueOf(policy); - } - catch(Exception e) - { - throw new IllegalArgumentException("Invalid transaction synchronization policy '" + policy + "'. " + e.getMessage()); - } - } - - private ReplicatedEnvironmentFacade getReplicatedEnvironmentFacade() - { - return (ReplicatedEnvironmentFacade) _configurationStore.getEnvironmentFacade(); - } - - @Override - public Long getStoreUnderfullSize() - { - return _storeUnderfullSize; - } - - @Override - public Long getStoreOverfullSize() - { - return _storeOverfullSize; - } - - @Override - public void onValidate() - { - super.onValidate(); - - validateTransactionSynchronizationPolicy(this.getLocalTransactionSynchronizationPolicy()); - validateTransactionSynchronizationPolicy(this.getRemoteTransactionSynchronizationPolicy()); - } - -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHost.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHost.java deleted file mode 100644 index ac8d33685a..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHost.java +++ /dev/null @@ -1,49 +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.virtualhost.berkeleydb; - - -import org.apache.qpid.server.exchange.ExchangeImpl; -import org.apache.qpid.server.model.ManagedAttribute; -import org.apache.qpid.server.model.ManagedContextDefault; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.store.SizeMonitoringSettings; -import org.apache.qpid.server.virtualhost.VirtualHostImpl; - -public interface BDBVirtualHost<X extends BDBVirtualHost<X>> extends VirtualHostImpl<X, AMQQueue<?>, ExchangeImpl<?>>, org.apache.qpid.server.store.FileBasedSettings, SizeMonitoringSettings -{ - - String STORE_PATH = "storePath"; - - // Default the JE cache to 5% of total memory, but no less than 10Mb and no more than 200Mb - @ManagedContextDefault(name="je.maxMemory") - long DEFAULT_JE_CACHE_SIZE = Math.max(10l*1024l*1024l, - Math.min(200l*1024l*1024l, - Runtime.getRuntime().maxMemory()/20l)); - - @ManagedAttribute(mandatory = true, defaultValue = "${qpid.work_dir}${file.separator}${this:name}${file.separator}messages") - String getStorePath(); - - @ManagedAttribute(mandatory = true, defaultValue = "0") - Long getStoreUnderfullSize(); - - @ManagedAttribute(mandatory = true, defaultValue = "0") - Long getStoreOverfullSize(); -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHostImpl.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHostImpl.java deleted file mode 100644 index ad1398ae76..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHostImpl.java +++ /dev/null @@ -1,78 +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.virtualhost.berkeleydb; - -import java.util.Map; - -import org.apache.qpid.server.model.ManagedAttributeField; -import org.apache.qpid.server.model.ManagedObject; -import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; -import org.apache.qpid.server.model.VirtualHostNode; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.berkeleydb.BDBMessageStore; -import org.apache.qpid.server.virtualhost.AbstractVirtualHost; - -@ManagedObject(category = false, type = BDBVirtualHostImpl.VIRTUAL_HOST_TYPE) -public class BDBVirtualHostImpl extends AbstractVirtualHost<BDBVirtualHostImpl> implements BDBVirtualHost<BDBVirtualHostImpl> -{ - public static final String VIRTUAL_HOST_TYPE = "BDB"; - - @ManagedAttributeField - private String _storePath; - - @ManagedAttributeField - private Long _storeUnderfullSize; - - @ManagedAttributeField - private Long _storeOverfullSize; - - @ManagedObjectFactoryConstructor - public BDBVirtualHostImpl(final Map<String, Object> attributes, - final VirtualHostNode<?> virtualHostNode) - { - super(attributes, virtualHostNode); - } - - - @Override - protected MessageStore createMessageStore() - { - return new BDBMessageStore(); - } - - @Override - public String getStorePath() - { - return _storePath; - } - - @Override - public Long getStoreUnderfullSize() - { - return _storeUnderfullSize; - } - - @Override - public Long getStoreOverfullSize() - { - return _storeOverfullSize; - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNode.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNode.java deleted file mode 100644 index d8a2ba22a9..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNode.java +++ /dev/null @@ -1,55 +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.virtualhostnode.berkeleydb; - -import org.apache.qpid.server.model.DerivedAttribute; -import org.apache.qpid.server.model.ManagedAttribute; -import org.apache.qpid.server.model.ManagedObject; -import org.apache.qpid.server.model.RemoteReplicationNode; - -@ManagedObject(category=false, creatable=false) -public interface BDBHARemoteReplicationNode<X extends BDBHARemoteReplicationNode<X>> extends RemoteReplicationNode<X> -{ - String GROUP_NAME = "groupName"; - String ADDRESS = "address"; - String ROLE = "role"; - String LAST_KNOWN_REPLICATION_TRANSACTION_ID = "lastKnownReplicationTransactionId"; - String JOIN_TIME = "joinTime"; - String MONITOR = "monitor"; - - @DerivedAttribute - String getGroupName(); - - @DerivedAttribute - String getAddress(); - - @ManagedAttribute(persist = false) - NodeRole getRole(); - - @DerivedAttribute - long getJoinTime(); - - @DerivedAttribute - long getLastKnownReplicationTransactionId(); - - @DerivedAttribute - boolean isMonitor(); -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeImpl.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeImpl.java deleted file mode 100644 index 0a9f076021..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeImpl.java +++ /dev/null @@ -1,239 +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.virtualhostnode.berkeleydb; - -import java.util.Map; -import java.util.Set; - -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import com.sleepycat.je.rep.MasterStateException; - -import org.apache.qpid.server.configuration.IllegalConfigurationException; -import org.apache.qpid.server.logging.EventLogger; -import org.apache.qpid.server.logging.messages.HighAvailabilityMessages; -import org.apache.qpid.server.logging.subjects.BDBHAVirtualHostNodeLogSubject; -import org.apache.qpid.server.logging.subjects.GroupLogSubject; -import org.apache.qpid.server.model.AbstractConfiguredObject; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.model.IllegalStateTransitionException; -import org.apache.qpid.server.model.ManagedAttributeField; -import org.apache.qpid.server.model.State; -import org.apache.qpid.server.model.StateTransition; -import org.apache.qpid.server.model.SystemConfig; -import org.apache.qpid.server.model.VirtualHostNode; -import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacade; - -public class BDBHARemoteReplicationNodeImpl extends AbstractConfiguredObject<BDBHARemoteReplicationNodeImpl> implements BDBHARemoteReplicationNode<BDBHARemoteReplicationNodeImpl> -{ - - private final ReplicatedEnvironmentFacade _replicatedEnvironmentFacade; - private final String _address; - private final Broker _broker; - - private volatile long _joinTime; - private volatile long _lastTransactionId; - - @ManagedAttributeField(afterSet="afterSetRole") - private volatile NodeRole _role; - - private final boolean _isMonitor; - private BDBHAVirtualHostNodeLogSubject _virtualHostNodeLogSubject; - private GroupLogSubject _groupLogSubject; - private volatile NodeRole _lastKnownRole; - - public BDBHARemoteReplicationNodeImpl(BDBHAVirtualHostNode<?> virtualHostNode, Map<String, Object> attributes, ReplicatedEnvironmentFacade replicatedEnvironmentFacade) - { - super(parentsMap(virtualHostNode), attributes); - _broker = virtualHostNode.getParent(Broker.class); - _address = (String)attributes.get(ADDRESS); - _replicatedEnvironmentFacade = replicatedEnvironmentFacade; - setState(State.ACTIVE); - - _role = NodeRole.UNREACHABLE; - _lastKnownRole = NodeRole.UNREACHABLE; - - _isMonitor = (Boolean)attributes.get(MONITOR); - } - - @Override - public String getGroupName() - { - return _replicatedEnvironmentFacade.getGroupName(); - } - - @Override - public String getAddress() - { - return _address; - } - - @Override - public NodeRole getRole() - { - return _lastKnownRole; - } - - @Override - public long getJoinTime() - { - return _joinTime; - } - - @Override - public long getLastKnownReplicationTransactionId() - { - return _lastTransactionId; - } - - @Override - public boolean isMonitor() - { - return _isMonitor; - } - - @Override - public void deleted() - { - super.deleted(); - } - - @Override - public String toString() - { - return getClass().getSimpleName() + "[id=" + getId() + ", name=" + getName() + ", address=" + getAddress() - + ", state=" + getState() + ", role=" + getRole() + "]"; - } - - @StateTransition(currentState = {State.ACTIVE, State.UNAVAILABLE}, desiredState = State.DELETED) - private ListenableFuture<Void> doDelete() - { - String nodeName = getName(); - - getEventLogger().message(_virtualHostNodeLogSubject, HighAvailabilityMessages.DELETED()); - - try - { - _replicatedEnvironmentFacade.removeNodeFromGroup(nodeName); - setState(State.DELETED); - deleted(); - } - catch(MasterStateException e) - { - throw new IllegalStateTransitionException("Node '" + nodeName + "' cannot be deleted when role is a master"); - } - catch (Exception e) - { - throw new IllegalStateTransitionException("Unexpected exception on node '" + nodeName + "' deletion", e); - } - - return Futures.immediateFuture(null); - } - - protected void afterSetRole() - { - try - { - String nodeName = getName(); - getEventLogger().message(_groupLogSubject, HighAvailabilityMessages.TRANSFER_MASTER(getName(), getAddress())); - - _replicatedEnvironmentFacade.transferMasterAsynchronously(nodeName); - } - catch (Exception e) - { - throw new IllegalConfigurationException("Cannot transfer mastership to '" + getName() + "'", e); - } - } - - @Override - protected void validateChange(final ConfiguredObject<?> proxyForValidation, final Set<String> changedAttributes) - { - super.validateChange(proxyForValidation, changedAttributes); - if (changedAttributes.contains(ROLE)) - { - NodeRole currentRole = getRole(); - if (NodeRole.REPLICA != currentRole) - { - throw new IllegalArgumentException("Cannot transfer mastership when not in replica role." - + " Current role " + currentRole); - } - NodeRole newRole = (NodeRole) ((BDBHARemoteReplicationNode<?>) proxyForValidation).getAttribute(ROLE); - if (NodeRole.MASTER != newRole) - { - throw new IllegalArgumentException("Changing role to other value then " + NodeRole.MASTER + " is unsupported"); - } - } - - if (changedAttributes.contains(JOIN_TIME)) - { - throw new IllegalArgumentException("Cannot change derived attribute " + JOIN_TIME); - } - - if (changedAttributes.contains(LAST_KNOWN_REPLICATION_TRANSACTION_ID)) - { - throw new IllegalArgumentException("Cannot change derived attribute " + LAST_KNOWN_REPLICATION_TRANSACTION_ID); - } - } - - void setRole(NodeRole role) - { - _lastKnownRole = role; - _role = role; - updateModelStateFromRole(role); - } - - void setJoinTime(long joinTime) - { - _joinTime = joinTime; - } - - void setLastTransactionId(long lastTransactionId) - { - _lastTransactionId = lastTransactionId; - } - - private void updateModelStateFromRole(NodeRole role) - { - State currentState = getState(); - if (currentState == State.DELETED) - { - return; - } - - boolean isActive = NodeRole.MASTER == role || NodeRole.REPLICA == role; - setState(isActive ? State.ACTIVE : State.UNAVAILABLE); - } - - @Override - public void onValidate() - { - super.onValidate(); - _virtualHostNodeLogSubject = new BDBHAVirtualHostNodeLogSubject(getGroupName(), getName()); - _groupLogSubject = new GroupLogSubject(getGroupName()); - } - - private EventLogger getEventLogger() - { - return ((SystemConfig)getParent(VirtualHostNode.class).getParent(Broker.class).getParent(SystemConfig.class)).getEventLogger(); - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNode.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNode.java deleted file mode 100644 index a23f4056fd..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNode.java +++ /dev/null @@ -1,77 +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.virtualhostnode.berkeleydb; - -import java.util.List; - -import org.apache.qpid.server.model.DerivedAttribute; -import org.apache.qpid.server.model.ManagedAttribute; -import org.apache.qpid.server.store.berkeleydb.HASettings; - - -public interface BDBHAVirtualHostNode<X extends BDBHAVirtualHostNode<X>> extends BDBVirtualHostNode<X>, HASettings -{ - public static final String GROUP_NAME = "groupName"; - public static final String ADDRESS = "address"; - public static final String HELPER_ADDRESS = "helperAddress"; - public static final String DURABILITY = "durability"; - public static final String DESIGNATED_PRIMARY = "designatedPrimary"; - public static final String PRIORITY = "priority"; - public static final String QUORUM_OVERRIDE = "quorumOverride"; - public static final String ROLE = "role"; - public static final String LAST_KNOWN_REPLICATION_TRANSACTION_ID = "lastKnownReplicationTransactionId"; - public static final String JOIN_TIME = "joinTime"; - public static final String HELPER_NODE_NAME = "helperNodeName"; - public static final String PERMITTED_NODES = "permittedNodes"; - - @ManagedAttribute(mandatory=true) - String getGroupName(); - - @ManagedAttribute(mandatory=true) - String getAddress(); - - @ManagedAttribute(mandatory=true) - String getHelperAddress(); - - @ManagedAttribute(defaultValue = "false") - boolean isDesignatedPrimary(); - - @ManagedAttribute(defaultValue = "1") - int getPriority(); - - @ManagedAttribute(defaultValue = "0") - int getQuorumOverride(); - - @ManagedAttribute(persist = false, defaultValue = "WAITING") - NodeRole getRole(); - - @DerivedAttribute - Long getLastKnownReplicationTransactionId(); - - @DerivedAttribute - Long getJoinTime(); - - @ManagedAttribute(persist = false) - String getHelperNodeName(); - - @ManagedAttribute(persist = true) - List<String> getPermittedNodes(); -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java deleted file mode 100644 index 9b5aef5405..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java +++ /dev/null @@ -1,1261 +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.virtualhostnode.berkeleydb; - -import java.io.File; -import java.net.InetSocketAddress; -import java.net.URI; -import java.net.URISyntaxException; -import java.security.PrivilegedAction; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicReference; - -import javax.security.auth.Subject; - -import com.google.common.util.concurrent.FutureCallback; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.SettableFuture; -import com.sleepycat.je.DatabaseException; -import com.sleepycat.je.LogWriteException; -import com.sleepycat.je.rep.NodeState; -import com.sleepycat.je.rep.NodeType; -import com.sleepycat.je.rep.ReplicatedEnvironment; -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 com.sleepycat.je.rep.utilint.HostPortPair; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.server.configuration.IllegalConfigurationException; -import org.apache.qpid.server.configuration.updater.Task; -import org.apache.qpid.server.logging.messages.BrokerMessages; -import org.apache.qpid.server.logging.messages.ConfigStoreMessages; -import org.apache.qpid.server.logging.messages.HighAvailabilityMessages; -import org.apache.qpid.server.logging.subjects.BDBHAVirtualHostNodeLogSubject; -import org.apache.qpid.server.logging.subjects.GroupLogSubject; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.BrokerModel; -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.model.ManagedAttributeField; -import org.apache.qpid.server.model.ManagedObject; -import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; -import org.apache.qpid.server.model.RemoteReplicationNode; -import org.apache.qpid.server.model.State; -import org.apache.qpid.server.model.StateTransition; -import org.apache.qpid.server.model.SystemConfig; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.store.ConfiguredObjectRecord; -import org.apache.qpid.server.store.ConfiguredObjectRecordImpl; -import org.apache.qpid.server.store.DurableConfigurationStore; -import org.apache.qpid.server.store.VirtualHostStoreUpgraderAndRecoverer; -import org.apache.qpid.server.store.berkeleydb.BDBConfigurationStore; -import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacade; -import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacadeFactory; -import org.apache.qpid.server.store.berkeleydb.replication.ReplicationGroupListener; -import org.apache.qpid.server.util.PortUtil; -import org.apache.qpid.server.util.ServerScopedRuntimeException; -import org.apache.qpid.server.virtualhost.berkeleydb.BDBHAVirtualHostImpl; -import org.apache.qpid.server.virtualhostnode.AbstractVirtualHostNode; - -@ManagedObject( category = false, type = BDBHAVirtualHostNodeImpl.VIRTUAL_HOST_NODE_TYPE, - validChildTypes = "org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNodeImpl#getSupportedChildTypes()" ) -public class BDBHAVirtualHostNodeImpl extends AbstractVirtualHostNode<BDBHAVirtualHostNodeImpl> implements - BDBHAVirtualHostNode<BDBHAVirtualHostNodeImpl> -{ - public static final String VIRTUAL_HOST_NODE_TYPE = "BDB_HA"; - public static final String VIRTUAL_HOST_PRINCIPAL_NAME_FORMAT = "grp(/{0})/vhn(/{1})"; - - /** - * Length of time we synchronously await the a JE mutation to complete. It is not considered an error if we exceed this timeout, although a - * a warning will be logged. - */ - private static final int MUTATE_JE_TIMEOUT_MS = 100; - - private static final Logger LOGGER = LoggerFactory.getLogger(BDBHAVirtualHostNodeImpl.class); - - private final AtomicReference<ReplicatedEnvironmentFacade> _environmentFacade = new AtomicReference<>(); - - private final AtomicReference<NodeRole> _lastRole = new AtomicReference<>(NodeRole.DETACHED); - private final SystemConfig _systemConfig; - private BDBHAVirtualHostNodeLogSubject _virtualHostNodeLogSubject; - private GroupLogSubject _groupLogSubject; - private String _virtualHostNodePrincipalName; - - @ManagedAttributeField - private String _storePath; - - @ManagedAttributeField - private String _groupName; - - @ManagedAttributeField - private String _helperAddress; - - @ManagedAttributeField - private String _address; - - @ManagedAttributeField(afterSet="postSetDesignatedPrimary") - private boolean _designatedPrimary; - - @ManagedAttributeField(afterSet="postSetPriority") - private int _priority; - - @ManagedAttributeField(afterSet="postSetQuorumOverride") - private int _quorumOverride; - - @ManagedAttributeField(afterSet="postSetRole") - private NodeRole _role; - - @ManagedAttributeField - private String _helperNodeName; - - @ManagedAttributeField(afterSet = "postSetPermittedNodes") - private List<String> _permittedNodes; - - @ManagedObjectFactoryConstructor - public BDBHAVirtualHostNodeImpl(Map<String, Object> attributes, Broker<?> broker) - { - super(broker, attributes); - _systemConfig = broker.getParent(SystemConfig.class); - } - - @Override - protected void validateChange(final ConfiguredObject<?> proxyForValidation, final Set<String> changedAttributes) - { - super.validateChange(proxyForValidation, changedAttributes); - BDBHAVirtualHostNode<?> proposed = (BDBHAVirtualHostNode<?>)proxyForValidation; - - if (changedAttributes.contains(ROLE)) - { - NodeRole currentRole = getRole(); - if (NodeRole.REPLICA != currentRole) - { - throw new IllegalStateException("Cannot transfer mastership when not a " + NodeRole.REPLICA + ", current role is " + currentRole); - } - if (NodeRole.MASTER != proposed.getAttribute(ROLE)) - { - throw new IllegalArgumentException("Changing role to other value then " + NodeRole.MASTER + " is unsupported"); - } - } - - if (changedAttributes.contains(PERMITTED_NODES)) - { - validatePermittedNodes(proposed.getPermittedNodes()); - } - } - - @Override - public String getStorePath() - { - return _storePath; - } - - @Override - public String getGroupName() - { - return _groupName; - } - - @Override - public String getHelperAddress() - { - return _helperAddress; - } - - @Override - public String getAddress() - { - return _address; - } - - @Override - public boolean isDesignatedPrimary() - { - return _designatedPrimary; - } - - @Override - public int getPriority() - { - return _priority; - } - - @Override - public int getQuorumOverride() - { - return _quorumOverride; - } - - @Override - public NodeRole getRole() - { - return _lastRole.get(); - } - - @Override - public Long getLastKnownReplicationTransactionId() - { - ReplicatedEnvironmentFacade environmentFacade = getReplicatedEnvironmentFacade(); - if (environmentFacade != null) - { - return environmentFacade.getLastKnownReplicationTransactionId(); - } - return -1L; - } - - @Override - public Long getJoinTime() - { - ReplicatedEnvironmentFacade environmentFacade = getReplicatedEnvironmentFacade(); - if (environmentFacade != null) - { - return environmentFacade.getJoinTime(); - } - return -1L; - } - - @Override - public String getHelperNodeName() - { - return _helperNodeName; - } - - @Override - public List<String> getPermittedNodes() - { - return _permittedNodes; - } - - @SuppressWarnings("rawtypes") - @Override - public Collection<? extends RemoteReplicationNode> getRemoteReplicationNodes() - { - Collection<RemoteReplicationNode> remoteNodes = getChildren(RemoteReplicationNode.class); - return (Collection<? extends RemoteReplicationNode>)remoteNodes; - } - - @Override - public String toString() - { - return "BDBHAVirtualHostNodeImpl [id=" + getId() + ", name=" + getName() + ", storePath=" + _storePath + ", groupName=" + _groupName + ", address=" + _address - + ", state=" + getState() + ", priority=" + _priority + ", designatedPrimary=" + _designatedPrimary + ", quorumOverride=" + _quorumOverride + ", role=" + getRole() + "]"; - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Override - protected <C extends ConfiguredObject> ListenableFuture<C> addChildAsync(Class<C> childClass, Map<String, Object> attributes, - ConfiguredObject... otherParents) - { - if(childClass == VirtualHost.class) - { - return getObjectFactory().createAsync(childClass, attributes, this); - } - return super.addChildAsync(childClass, attributes, otherParents); - } - - @Override - public BDBConfigurationStore getConfigurationStore() - { - return (BDBConfigurationStore) super.getConfigurationStore(); - } - - @Override - public void onCreate() - { - super.onCreate(); - if (!isFirstNodeInAGroup()) - { - List<String> permittedNodes = new ArrayList<>(getPermittedNodesFromHelper()); - setAttribute(PERMITTED_NODES, null, permittedNodes); - } - getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.CREATED()); - } - - @Override - public void onOpen() - { - validatePermittedNodesFormat(_permittedNodes); - super.onOpen(); - } - - protected ReplicatedEnvironmentFacade getReplicatedEnvironmentFacade() - { - return _environmentFacade.get(); - } - - @Override - protected DurableConfigurationStore createConfigurationStore() - { - return new BDBConfigurationStore(new ReplicatedEnvironmentFacadeFactory(), VirtualHost.class); - } - - @Override - protected ListenableFuture<Void> activate() - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Activating virtualhost node " + this); - } - - // activating the environment does not cause a state change. Adjust the role - // so that our observers will see WAITING rather than our previous role in the group. - // the role will change again after the election at which point it will become master or replica. - _lastRole.set(NodeRole.WAITING); - attributeSet(ROLE, _role, NodeRole.WAITING); - - getConfigurationStore().openConfigurationStore(this, false); - - getEventLogger().message(getConfigurationStoreLogSubject(), ConfigStoreMessages.CREATED()); - getEventLogger().message(getConfigurationStoreLogSubject(), ConfigStoreMessages.STORE_LOCATION(getStorePath())); - - ReplicatedEnvironmentFacade environmentFacade = (ReplicatedEnvironmentFacade) getConfigurationStore().getEnvironmentFacade(); - if (environmentFacade == null) - { - throw new IllegalStateException("Environment facade is not created"); - } - - try - { - Set<ReplicationNode> remoteNodes = environmentFacade.getEnvironment().getGroup().getNodes(); - for (ReplicationNode node : remoteNodes) - { - String nodeAddress = node.getHostName() + ":" + node.getPort(); - if (!_permittedNodes.contains(nodeAddress)) - { - getEventLogger().message(getGroupLogSubject(), HighAvailabilityMessages.INTRUDER_DETECTED(node.getName(), nodeAddress)); - shutdownOnIntruder(nodeAddress); - - throw new IllegalStateException("Intruder node detected: " + nodeAddress); - } - } - } - catch (DatabaseException dbe) - { - environmentFacade.handleDatabaseException("DB exception while checking for intruder node", dbe); - } - - if (_environmentFacade.compareAndSet(null, environmentFacade)) - { - environmentFacade.setStateChangeListener(new EnvironmentStateChangeListener()); - environmentFacade.setReplicationGroupListener(new RemoteNodesDiscoverer()); - environmentFacade.setPermittedNodes(_permittedNodes); - } - - return Futures.immediateFuture(null); - } - - @StateTransition( currentState = { State.UNINITIALIZED, State.ACTIVE, State.ERRORED }, desiredState = State.STOPPED ) - protected ListenableFuture<Void> doStop() - { - final SettableFuture<Void> returnVal = SettableFuture.create(); - - ListenableFuture<Void> superFuture = super.doStop(); - Futures.addCallback(superFuture, new FutureCallback<Void>() - { - @Override - public void onSuccess(final Void result) - { - doFinally(); - } - - @Override - public void onFailure(final Throwable t) - { - doFinally(); - } - - private void doFinally() - { - try - { - closeEnvironment(); - - // closing the environment does not cause a state change. Adjust the role - // so that our observers will see DETACHED rather than our previous role in the group. - _lastRole.set(NodeRole.DETACHED); - attributeSet(ROLE, _role, NodeRole.DETACHED); - } - finally - { - returnVal.set(null); - } - - } - }); - return returnVal; - } - - private void closeEnvironment() - { - ReplicatedEnvironmentFacade environmentFacade = getReplicatedEnvironmentFacade(); - if (environmentFacade != null && _environmentFacade.compareAndSet(environmentFacade, null)) - { - environmentFacade.close(); - } - } - - @StateTransition( currentState = { State.ACTIVE, State.STOPPED, State.ERRORED}, desiredState = State.DELETED ) - protected ListenableFuture<Void> doDelete() - { - - // get helpers before close. on close all children are closed and not available anymore - final Set<InetSocketAddress> helpers = getRemoteNodeAddresses(); - return doAfter(super.doDelete(),new Runnable() - { - @Override - public void run() - { - if (getConfigurationStore() != null) - { - getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.DELETED()); - } - - if (getState() == State.DELETED && !helpers.isEmpty()) - { - try - { - new ReplicationGroupAdmin(_groupName, helpers).removeMember(getName()); - } - catch(DatabaseException e) - { - LOGGER.warn("The deletion of node " + this + " on remote nodes failed due to: " + e.getMessage() - + ". To finish deletion a removal of the node from any of remote nodes (" + helpers + ") is required."); - } - } - - } - }); - - - } - - @Override - protected ListenableFuture<Void> deleteVirtualHostIfExists() - { - ReplicatedEnvironmentFacade replicatedEnvironmentFacade = getReplicatedEnvironmentFacade(); - if (replicatedEnvironmentFacade != null && replicatedEnvironmentFacade.isMaster() - && replicatedEnvironmentFacade.getNumberOfElectableGroupMembers() == 1) - { - return super.deleteVirtualHostIfExists(); - } - else - { - return closeVirtualHostIfExist(); - } - } - - private Set<InetSocketAddress> getRemoteNodeAddresses() - { - Set<InetSocketAddress> helpers = new HashSet<InetSocketAddress>(); - @SuppressWarnings("rawtypes") - Collection<? extends RemoteReplicationNode> remoteNodes = getRemoteReplicationNodes(); - for (RemoteReplicationNode<?> node : remoteNodes) - { - BDBHARemoteReplicationNode<?> bdbHaRemoteReplicationNode = (BDBHARemoteReplicationNode<?>)node; - String remoteNodeAddress = bdbHaRemoteReplicationNode.getAddress(); - helpers.add(HostPortPair.getSocket(remoteNodeAddress)); - } - return helpers; - } - - @Override - protected void onClose() - { - try - { - super.onClose(); - } - finally - { - closeEnvironment(); - } - } - - @Override - protected void postResolve() - { - super.postResolve(); - _virtualHostNodeLogSubject = new BDBHAVirtualHostNodeLogSubject(getGroupName(), getName()); - _groupLogSubject = new GroupLogSubject(getGroupName()); - _virtualHostNodePrincipalName = MessageFormat.format(VIRTUAL_HOST_PRINCIPAL_NAME_FORMAT, getGroupName(), getName()); - } - - @Override - public void validateOnCreate() - { - super.validateOnCreate(); - - validateAddress(); - - validateStorePath(); - - if (!isFirstNodeInAGroup()) - { - getPermittedNodesFromHelper(); - } - } - - private Collection<String> getPermittedNodesFromHelper() - { - int dbPingSocketTimeout = getContextKeys(false).contains("qpid.bdb.ha.db_ping_socket_timeout") ? getContextValue(Integer.class, "qpid.bdb.ha.db_ping_socket_timeout") : 10000 /* JE's own default */; - return ReplicatedEnvironmentFacade.connectToHelperNodeAndCheckPermittedHosts(getName(), getAddress(), getGroupName(), getHelperNodeName(), getHelperAddress(), dbPingSocketTimeout); - } - - private void validateStorePath() - { - File storePath = new File(getStorePath()); - while (!storePath.exists()) - { - storePath = storePath.getParentFile(); - if (storePath == null) - { - throw new IllegalConfigurationException(String.format("Store path '%s' is invalid", getStorePath())); - } - } - - if (!storePath.isDirectory()) - { - throw new IllegalConfigurationException(String.format("Store path '%s' is not a folder", getStorePath())); - } - - if (!storePath.canWrite()) - { - throw new IllegalConfigurationException(String.format("Store path '%s' is not writable", getStorePath())); - } - - } - - private void validateAddress() - { - String address = getAddress(); - - URI uri = addressToURI(address); - - if (!PortUtil.isPortAvailable(uri.getHost(), uri.getPort())) - { - throw new IllegalConfigurationException(String.format("Cannot bind to address '%s'. Address is already in use.", address)); - } - } - - private URI addressToURI(String address) - { - if (address == null || "".equals(address)) - { - throw new IllegalConfigurationException("Node address is not set"); - } - - URI uri = null; - try - { - uri = new URI( "tcp://" + address); - } - catch (URISyntaxException e) - { - throw new IllegalConfigurationException(String.format("Invalid address specified '%s'. ", address)); - } - return uri; - } - - private void onMaster() - { - try - { - closeVirtualHostIfExist().get(); - - getConfigurationStore().upgradeStoreStructure(); - - getEventLogger().message(getConfigurationStoreLogSubject(), ConfigStoreMessages.RECOVERY_START()); - VirtualHostStoreUpgraderAndRecoverer upgraderAndRecoverer = new VirtualHostStoreUpgraderAndRecoverer(this); - upgraderAndRecoverer.perform(getConfigurationStore()); - getEventLogger().message(getConfigurationStoreLogSubject(), ConfigStoreMessages.RECOVERY_COMPLETE()); - - VirtualHost<?,?,?> host = getVirtualHost(); - - if (host == null) - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Creating new virtualhost with name : " + getGroupName()); - } - ConfiguredObjectRecord[] initialRecords = getInitialRecords(); - if(initialRecords != null && initialRecords.length > 0) - { - getConfigurationStore().update(true, initialRecords); - getEventLogger().message(getConfigurationStoreLogSubject(), ConfigStoreMessages.RECOVERY_START()); - upgraderAndRecoverer = new VirtualHostStoreUpgraderAndRecoverer(this); - upgraderAndRecoverer.perform(getConfigurationStore()); - getEventLogger().message(getConfigurationStoreLogSubject(), ConfigStoreMessages.RECOVERY_COMPLETE()); - setAttribute(VIRTUALHOST_INITIAL_CONFIGURATION, getVirtualHostInitialConfiguration(), "{}" ); - host = getVirtualHost(); - if(host != null) - { - final VirtualHost<?,?,?> recoveredHost = host; - Subject.doAs(SecurityManager.getSubjectWithAddedSystemRights(), new PrivilegedAction<Object>() - { - @Override - public Object run() - { - recoveredHost.open(); - return null; - } - }); - } - } - else - { - Map<String, Object> hostAttributes = new HashMap<>(); - - hostAttributes.put(VirtualHost.MODEL_VERSION, BrokerModel.MODEL_VERSION); - hostAttributes.put(VirtualHost.NAME, getGroupName()); - hostAttributes.put(VirtualHost.TYPE, BDBHAVirtualHostImpl.VIRTUAL_HOST_TYPE); - host = createChild(VirtualHost.class, hostAttributes); - } - - } - else - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Recovered virtualhost with name : " + getGroupName()); - } - - final VirtualHost<?,?,?> recoveredHost = host; - Subject.doAs(SecurityManager.getSubjectWithAddedSystemRights(), new PrivilegedAction<Object>() - { - @Override - public Object run() - { - recoveredHost.open(); - return null; - } - }); - } - - } - catch (Exception e) - { - LOGGER.error("Failed to activate on hearing MASTER change event", e); - } - } - - private void onReplica() - { - createReplicaVirtualHost(); - } - - private void createReplicaVirtualHost() - { - try - { - closeVirtualHostIfExist().get(); - - Map<String, Object> hostAttributes = new HashMap<>(); - hostAttributes.put(VirtualHost.MODEL_VERSION, BrokerModel.MODEL_VERSION); - hostAttributes.put(VirtualHost.NAME, getGroupName()); - hostAttributes.put(VirtualHost.TYPE, "BDB_HA_REPLICA"); - createChild(VirtualHost.class, hostAttributes); - } - catch (Exception e) - { - LOGGER.error("Failed to create a replica virtualhost", e); - } - } - - protected ListenableFuture<Void> closeVirtualHostIfExist() - { - final VirtualHost<?,?,?> virtualHost = getVirtualHost(); - if (virtualHost!= null) - { - return doAfter(virtualHost.closeAsync(), new Runnable() - { - @Override - public void run() - { - childRemoved(virtualHost); - - } - }); - } - else - { - return Futures.immediateFuture(null); - } - } - - private class EnvironmentStateChangeListener 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 + " for " + getName()); - } - NodeRole previousRole = getRole(); - try - { - switch (state) - { - case MASTER: - onMaster(); - break; - case REPLICA: - onReplica(); - break; - case DETACHED: - closeVirtualHostIfExist().get(); - break; - case UNKNOWN: - closeVirtualHostIfExist().get(); - break; - default: - LOGGER.error("Unexpected state change: " + state); - } - } - catch (InterruptedException | ExecutionException e) - { - throw new ServerScopedRuntimeException(e); - } - finally - { - NodeRole newRole = NodeRole.fromJeState(state); - _lastRole.set(newRole); - attributeSet(ROLE, _role, newRole); - getEventLogger().message(getGroupLogSubject(), - HighAvailabilityMessages.ROLE_CHANGED(getName(), getAddress(), previousRole.name(), newRole.name())); - } - } - } - - // used as post action by field _priority - @SuppressWarnings("unused") - private void postSetPriority() - { - ReplicatedEnvironmentFacade environmentFacade = getReplicatedEnvironmentFacade(); - if (environmentFacade != null) - { - try - { - environmentFacade.setPriority(_priority).get(MUTATE_JE_TIMEOUT_MS, TimeUnit.MILLISECONDS); - getEventLogger().message(getVirtualHostNodeLogSubject(), - HighAvailabilityMessages.PRIORITY_CHANGED(String.valueOf(_priority))); - } - catch (TimeoutException e) - { - LOGGER.warn("Change node priority did not complete within " + MUTATE_JE_TIMEOUT_MS + "ms. New value " + _priority + " will become effective once the JE task thread is free."); - } - catch (InterruptedException e) - { - Thread.currentThread().interrupt(); - } - catch (ExecutionException e) - { - throw new ServerScopedRuntimeException("Failed to set priority node to value " + _priority + " on " + this, e); - } - } - } - - // used as post action by field _designatedPrimary - @SuppressWarnings("unused") - private void postSetDesignatedPrimary() - { - ReplicatedEnvironmentFacade environmentFacade = getReplicatedEnvironmentFacade(); - if (environmentFacade != null) - { - try - { - environmentFacade.setDesignatedPrimary(_designatedPrimary).get(MUTATE_JE_TIMEOUT_MS, TimeUnit.MILLISECONDS); - getEventLogger().message(getVirtualHostNodeLogSubject(), - HighAvailabilityMessages.DESIGNATED_PRIMARY_CHANGED(String.valueOf(_designatedPrimary))); - } - catch (TimeoutException e) - { - LOGGER.warn("Change designated primary did not complete within " + MUTATE_JE_TIMEOUT_MS + "ms. New value " + _designatedPrimary + " will become effective once the JE task thread is free."); - } - catch (InterruptedException e) - { - Thread.currentThread().interrupt(); - } - catch (ExecutionException e) - { - throw new ServerScopedRuntimeException("Failed to set designated primary to value " + _designatedPrimary + " on " + this, e); - } - } - } - - // used as post action by field _quorumOverride - @SuppressWarnings("unused") - private void postSetQuorumOverride() - { - ReplicatedEnvironmentFacade environmentFacade = getReplicatedEnvironmentFacade(); - if (environmentFacade != null) - { - try - { - environmentFacade.setElectableGroupSizeOverride(_quorumOverride).get(MUTATE_JE_TIMEOUT_MS, TimeUnit.MILLISECONDS); - getEventLogger().message(getVirtualHostNodeLogSubject(), - HighAvailabilityMessages.QUORUM_OVERRIDE_CHANGED(String.valueOf(_quorumOverride))); - } - catch (TimeoutException e) - { - LOGGER.warn("Change quorum override did not complete within " + MUTATE_JE_TIMEOUT_MS + "ms. New value " + _quorumOverride + " will become effective once the JE task thread is free."); - } - catch (InterruptedException e) - { - Thread.currentThread().interrupt(); - } - catch (ExecutionException e) - { - throw new ServerScopedRuntimeException("Failed to set quorum override to value " + _quorumOverride + " on " + this, e); - } - } - } - - // used as post action by field _role - @SuppressWarnings("unused") - private void postSetRole() - { - ReplicatedEnvironmentFacade environmentFacade = getReplicatedEnvironmentFacade(); - if (environmentFacade != null) - { - try - { - getEventLogger().message(getGroupLogSubject(), HighAvailabilityMessages.TRANSFER_MASTER(getName(), getAddress())); - environmentFacade.transferMasterToSelfAsynchronously().get(MUTATE_JE_TIMEOUT_MS, TimeUnit.MILLISECONDS); - } - catch (TimeoutException e) - { - LOGGER.warn("Transfer master did not complete within " + MUTATE_JE_TIMEOUT_MS + "ms. Node may still be elected master at a later time."); - } - catch (InterruptedException e) - { - Thread.currentThread().interrupt(); - } - catch (ExecutionException e) - { - throw new ServerScopedRuntimeException("Failed to transfer master to " + this, e); - } - } - else - { - // Ignored - } - } - - private boolean isFirstNodeInAGroup() - { - return getHelperNodeName() == null; - } - - BDBHAVirtualHostNodeLogSubject getVirtualHostNodeLogSubject() - { - return _virtualHostNodeLogSubject; - } - - GroupLogSubject getGroupLogSubject() - { - return _groupLogSubject; - } - - @Override - protected ConfiguredObjectRecord enrichInitialVirtualHostRootRecord(final ConfiguredObjectRecord vhostRecord) - { - Map<String,Object> hostAttributes = new LinkedHashMap<>(vhostRecord.getAttributes()); - hostAttributes.put(VirtualHost.MODEL_VERSION, BrokerModel.MODEL_VERSION); - hostAttributes.put(VirtualHost.NAME, getGroupName()); - hostAttributes.put(VirtualHost.TYPE, BDBHAVirtualHostImpl.VIRTUAL_HOST_TYPE); - return new ConfiguredObjectRecordImpl(vhostRecord.getId(), vhostRecord.getType(), - hostAttributes, vhostRecord.getParents()); - } - - protected void postSetPermittedNodes() - { - ReplicatedEnvironmentFacade replicatedEnvironmentFacade = getReplicatedEnvironmentFacade(); - if (replicatedEnvironmentFacade != null) - { - replicatedEnvironmentFacade.setPermittedNodes(_permittedNodes); - } - } - - private void validatePermittedNodes(Collection<String> proposedPermittedNodes) - { - if (getRemoteReplicationNodes().size() > 0 && getRole() != NodeRole.MASTER && !(getState() == State.STOPPED || getState() == State.ERRORED)) - { - throw new IllegalArgumentException(String.format("Attribute '%s' can only be set on '%s' node or node in '%s' or '%s' state", PERMITTED_NODES, NodeRole.MASTER, State.STOPPED, State.ERRORED)); - } - else if (proposedPermittedNodes == null || proposedPermittedNodes.isEmpty()) - { - throw new IllegalArgumentException(String.format("Attribute '%s' is mandatory and must be set", PERMITTED_NODES)); - } - - if (_permittedNodes != null) - { - String missingNodeAddress = null; - - if (_permittedNodes.contains(getAddress()) && !proposedPermittedNodes.contains(getAddress())) - { - missingNodeAddress = getAddress(); - } - else - { - for (final RemoteReplicationNode<?> node : getRemoteReplicationNodes()) - { - final BDBHARemoteReplicationNode<?> bdbHaRemoteReplicationNode = (BDBHARemoteReplicationNode<?>) node; - final String remoteNodeAddress = bdbHaRemoteReplicationNode.getAddress(); - if (_permittedNodes.contains(remoteNodeAddress) && !proposedPermittedNodes.contains(remoteNodeAddress)) - { - missingNodeAddress = remoteNodeAddress; - break; - } - } - } - - if (missingNodeAddress != null) - { - throw new IllegalArgumentException(String.format("The current group node '%s' cannot be removed from '%s' as its already a group member", missingNodeAddress, PERMITTED_NODES)); - } - } - - validatePermittedNodesFormat(proposedPermittedNodes); - } - - private void validatePermittedNodesFormat(Collection<String> permittedNodes) - { - if (permittedNodes == null || permittedNodes.isEmpty()) - { - throw new IllegalConfigurationException("Permitted nodes are not set"); - } - - for (String permittedNode: permittedNodes) - { - addressToURI(permittedNode); - } - } - - private class RemoteNodesDiscoverer implements ReplicationGroupListener - { - @Override - public void onReplicationNodeAddedToGroup(final ReplicationNode node) - { - getTaskExecutor().submit(new VirtualHostNodeGroupTask() - { - @Override - public void perform() - { - addRemoteReplicationNode(node); - } - }); - } - - private void addRemoteReplicationNode(ReplicationNode node) - { - BDBHARemoteReplicationNodeImpl remoteNode = new BDBHARemoteReplicationNodeImpl(BDBHAVirtualHostNodeImpl.this, nodeToAttributes(node), getReplicatedEnvironmentFacade()); - remoteNode.create(); - childAdded(remoteNode); - getEventLogger().message(getGroupLogSubject(), HighAvailabilityMessages.ADDED(remoteNode.getName(), remoteNode.getAddress())); - } - - @Override - public void onReplicationNodeRecovered(final ReplicationNode node) - { - getTaskExecutor().submit(new VirtualHostNodeGroupTask() - { - @Override - public void perform() - { - recoverRemoteReplicationNode(node); - } - }); - } - - private void recoverRemoteReplicationNode(ReplicationNode node) - { - BDBHARemoteReplicationNodeImpl remoteNode = new BDBHARemoteReplicationNodeImpl(BDBHAVirtualHostNodeImpl.this, nodeToAttributes(node), getReplicatedEnvironmentFacade()); - remoteNode.registerWithParents(); - remoteNode.open(); - - getEventLogger().message(getGroupLogSubject(), HighAvailabilityMessages.JOINED(remoteNode.getName(), remoteNode.getAddress())); - } - - @Override - public void onReplicationNodeRemovedFromGroup(final ReplicationNode node) - { - getTaskExecutor().submit(new VirtualHostNodeGroupTask() - { - @Override - public void perform() - { - removeRemoteReplicationNode(node); - } - }); - } - - private void removeRemoteReplicationNode(ReplicationNode node) - { - BDBHARemoteReplicationNodeImpl remoteNode = getChildByName(BDBHARemoteReplicationNodeImpl.class, node.getName()); - if (remoteNode != null) - { - remoteNode.deleted(); - getEventLogger().message(getGroupLogSubject(), HighAvailabilityMessages.REMOVED(remoteNode.getName(), remoteNode.getAddress())); - } - } - - @Override - public void onNodeState(final ReplicationNode node, final NodeState nodeState) - { - Subject.doAs(SecurityManager.getSystemTaskSubject(_virtualHostNodePrincipalName), new PrivilegedAction<Void>() - { - @Override - public Void run() - { - processNodeState(node, nodeState); - return null; - } - }); - } - - private void processNodeState(ReplicationNode node, NodeState nodeState) - { - BDBHARemoteReplicationNodeImpl remoteNode = getChildByName(BDBHARemoteReplicationNodeImpl.class, node.getName()); - if (remoteNode != null) - { - final NodeRole previousRole = remoteNode.getRole(); - final NodeRole newRole; - if (nodeState == null) - { - newRole = NodeRole.UNREACHABLE; - remoteNode.setRole(newRole); - remoteNode.setLastTransactionId(-1); - if (previousRole != NodeRole.UNREACHABLE) - { - getEventLogger().message(getGroupLogSubject(), HighAvailabilityMessages.LEFT(remoteNode.getName(), remoteNode.getAddress())); - } - } - else - { - remoteNode.setJoinTime(nodeState.getJoinTime()); - remoteNode.setLastTransactionId(nodeState.getCurrentTxnEndVLSN()); - ReplicatedEnvironment.State state = nodeState.getNodeState(); - newRole = NodeRole.fromJeState(state); - remoteNode.setRole(newRole); - - if (previousRole == NodeRole.UNREACHABLE) - { - getEventLogger().message(getGroupLogSubject(), HighAvailabilityMessages.JOINED(remoteNode.getName(), remoteNode.getAddress())); - } - - if (NodeRole.MASTER == newRole) - { - byte[] applicationState = nodeState.getAppState(); - if (applicationState != null) - { - Set<String> permittedNodes = ReplicatedEnvironmentFacade.convertApplicationStateBytesToPermittedNodeList(applicationState); - if (_permittedNodes.size() != permittedNodes.size() || !_permittedNodes.containsAll(permittedNodes)) - { - if (_permittedNodes.contains(remoteNode.getAddress())) - { - setAttribute(PERMITTED_NODES, _permittedNodes, new ArrayList<String>(permittedNodes)); - } else - { - LOGGER.warn("Cannot accept the new permitted node list from the master as the master '" + remoteNode.getName() - + "' (" + remoteNode.getAddress() + ") was not in previous permitted list " + _permittedNodes); - } - } - } - else - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug(String.format("Application state returned by JE was 'null' so skipping permitted node handling: %s", nodeState)); - } - } - } - } - - if (newRole != previousRole) - { - getEventLogger().message(getGroupLogSubject(), HighAvailabilityMessages.ROLE_CHANGED(remoteNode.getName(), - remoteNode.getAddress(), - previousRole.name(), - newRole.name())); - } - } - } - - @Override - public boolean onIntruderNode(final ReplicationNode node) - { - return Subject.doAs(SecurityManager.getSystemTaskSubject(_virtualHostNodePrincipalName), new PrivilegedAction<Boolean>() - { - @Override - public Boolean run() - { - return processIntruderNode(node); - - } - }); - } - - private boolean processIntruderNode(ReplicationNode node) - { - final String hostAndPort = node.getHostName() + ":" + node.getPort(); - getEventLogger().message(getGroupLogSubject(), HighAvailabilityMessages.INTRUDER_DETECTED(node.getName(), hostAndPort)); - - boolean inManagementMode = getParent(Broker.class).isManagementMode(); - if (inManagementMode) - { - BDBHARemoteReplicationNodeImpl remoteNode = getChildByName(BDBHARemoteReplicationNodeImpl.class, node.getName()); - if (remoteNode == null) - { - addRemoteReplicationNode(node); - } - return true; - } - else - { - LOGGER.error(String.format("Intruder node '%s' from '%s' detected. Shutting down virtual host node " + - "'%s' (last role %s) owing to the presence of a node not in permitted nodes '%s'", - node.getName(), - hostAndPort, - BDBHAVirtualHostNodeImpl.this.getName(), - _lastRole.get(), - String.valueOf(BDBHAVirtualHostNodeImpl.this.getPermittedNodes()) )); - getTaskExecutor().submit(new Task<Void>() - { - @Override - public Void execute() - { - shutdownOnIntruder(hostAndPort); - return null; - } - }); - - return false; - } - } - - @Override - public void onNoMajority() - { - getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.QUORUM_LOST()); - } - - @Override - public void onNodeRolledback() - { - getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.NODE_ROLLEDBACK()); - } - - @Override - public void onException(Exception e) - { - if (e instanceof LogWriteException) - { - // TODO: Used when the node is a replica and it runs out of disk. Currently we cause the whole Broker - // to stop as that is what happens when a master runs out of disk. In the long term, we should - // close the node / transition to actual state ERROR. - - try - { - closeAsync(); - } - finally - { - _systemConfig.getEventLogger().message(BrokerMessages.FATAL_ERROR(e.getMessage())); - _systemConfig.getBrokerShutdownProvider().shutdown(1); - } - } - } - - private Map<String, Object> nodeToAttributes(ReplicationNode replicationNode) - { - Map<String, Object> attributes = new HashMap<String, Object>(); - attributes.put(ConfiguredObject.NAME, replicationNode.getName()); - attributes.put(ConfiguredObject.DURABLE, false); - attributes.put(BDBHARemoteReplicationNode.ADDRESS, replicationNode.getHostName() + ":" + replicationNode.getPort()); - attributes.put(BDBHARemoteReplicationNode.MONITOR, replicationNode.getType() == NodeType.MONITOR); - return attributes; - } - } - - protected void shutdownOnIntruder(String intruderHostAndPort) - { - LOGGER.info("Intruder detected (" + intruderHostAndPort + "), stopping and setting state to ERRORED"); - - State initialState = getState(); - try - { - stopAndSetStateTo(State.ERRORED); - } - catch (Exception e) - { - LOGGER.error("Unexpected exception on closing the node when intruder is detected ", e); - } - finally - { - closeEnvironment(); - _lastRole.set(NodeRole.DETACHED); - attributeSet(ROLE, _role, NodeRole.DETACHED); - } - notifyStateChanged(initialState, State.ERRORED); - } - - private abstract class VirtualHostNodeGroupTask implements Task<Void> - { - @Override - public Void execute() - { - return Subject.doAs(SecurityManager.getSystemTaskSubject(_virtualHostNodePrincipalName), new PrivilegedAction<Void>() - { - @Override - public Void run() - { - perform(); - return null; - } - }); - } - - abstract void perform(); - } - - public static Map<String, Collection<String>> getSupportedChildTypes() - { - return Collections.singletonMap(VirtualHost.class.getSimpleName(), (Collection<String>) Collections.singleton(BDBHAVirtualHostImpl.VIRTUAL_HOST_TYPE)); - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNode.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNode.java deleted file mode 100644 index 61b0d1882a..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNode.java +++ /dev/null @@ -1,31 +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.virtualhostnode.berkeleydb; - -import org.apache.qpid.server.model.ManagedAttribute; - -public interface BDBVirtualHostNode<X extends BDBVirtualHostNode<X>> extends org.apache.qpid.server.model.VirtualHostNode<X>, org.apache.qpid.server.store.FileBasedSettings -{ - String STORE_PATH = "storePath"; - - @ManagedAttribute(mandatory = true, defaultValue = "${qpid.work_dir}${file.separator}${this:name}${file.separator}config") - String getStorePath(); -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeImpl.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeImpl.java deleted file mode 100644 index 7e88ba23b7..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeImpl.java +++ /dev/null @@ -1,80 +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.virtualhostnode.berkeleydb; - -import java.util.Collection; -import java.util.Collections; -import java.util.Map; - -import org.apache.qpid.server.logging.messages.ConfigStoreMessages; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.ManagedAttributeField; -import org.apache.qpid.server.model.ManagedObject; -import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.store.DurableConfigurationStore; -import org.apache.qpid.server.store.berkeleydb.BDBConfigurationStore; -import org.apache.qpid.server.virtualhostnode.AbstractStandardVirtualHostNode; - -@ManagedObject(type = BDBVirtualHostNodeImpl.VIRTUAL_HOST_NODE_TYPE, category = false, - validChildTypes = "org.apache.qpid.server.virtualhostnode.berkeleydb.BDBVirtualHostNodeImpl#getSupportedChildTypes()") -public class BDBVirtualHostNodeImpl extends AbstractStandardVirtualHostNode<BDBVirtualHostNodeImpl> implements BDBVirtualHostNode<BDBVirtualHostNodeImpl> -{ - public static final String VIRTUAL_HOST_NODE_TYPE = "BDB"; - - @ManagedAttributeField - private String _storePath; - - @ManagedObjectFactoryConstructor - public BDBVirtualHostNodeImpl(Map<String, Object> attributes, Broker<?> parent) - { - super(attributes, parent); - } - - @Override - protected void writeLocationEventLog() - { - getEventLogger().message(getConfigurationStoreLogSubject(), ConfigStoreMessages.STORE_LOCATION(getStorePath())); - } - - @Override - protected DurableConfigurationStore createConfigurationStore() - { - return new BDBConfigurationStore(VirtualHost.class); - } - - @Override - public String getStorePath() - { - return _storePath; - } - - @Override - public String toString() - { - return getClass().getSimpleName() + " [id=" + getId() + ", name=" + getName() + ", storePath=" + getStorePath() + "]"; - } - - public static Map<String, Collection<String>> getSupportedChildTypes() - { - return Collections.singletonMap(VirtualHost.class.getSimpleName(), getSupportedVirtualHostTypes(true)); - } -} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/NodeRole.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/NodeRole.java deleted file mode 100644 index 2ea0d666be..0000000000 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/NodeRole.java +++ /dev/null @@ -1,56 +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.virtualhostnode.berkeleydb; - -import com.sleepycat.je.rep.ReplicatedEnvironment.State; - -public enum NodeRole -{ - /** Node is master. */ - MASTER, - /** Node is replica. */ - REPLICA, - /** Node is awaiting an election result, or may be awaiting more nodes to join in order that an election may be held. */ - WAITING, - /** - * (Remote) node is unreachable. Its virtual host node may be stopped, its Broker down, or a network problem may - * be preventing it from being contacted. - */ - UNREACHABLE, - /** (Local) node is not connected to the group */ - DETACHED; - - public static NodeRole fromJeState(final State state) - { - switch(state) - { - case DETACHED: - return DETACHED; - case UNKNOWN: - return WAITING; - case MASTER: - return MASTER; - case REPLICA: - return REPLICA; - default: - throw new IllegalArgumentException("Unrecognised JE node state " + state); - } - } -} diff --git a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhost/bdb/add.js b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhost/bdb/add.js deleted file mode 100644 index 323b8e9750..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhost/bdb/add.js +++ /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. - */ - -define(["dojo/_base/xhr", - "dojo/parser", - "dojo/dom", - "dojo/dom-construct", - "dojo/json", - "dijit/registry", - "dojo/text!virtualhost/sizemonitoring/add.html", - "qpid/common/util", - "dijit/form/ValidationTextBox", - "dijit/form/NumberTextBox", - "dojo/domReady!"], - function (xhr, parser, dom, domConstruct, json, registry, template, util) - { - return { - show: function (data) - { - this.containerNode = domConstruct.create("div", {innerHTML: template}, data.containerNode); - parser.parse(this.containerNode).then(function(instances) - { - registry.byId("addVirtualHost.storeUnderfullSize").set("regExpGen", util.numericOrContextVarRegexp); - registry.byId("addVirtualHost.storeOverfullSize").set("regExpGen", util.numericOrContextVarRegexp); - }); - } - }; - } -); diff --git a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhost/bdb/edit.js b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhost/bdb/edit.js deleted file mode 100644 index 076a27a3ae..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhost/bdb/edit.js +++ /dev/null @@ -1,34 +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. - */ -define(["dijit/registry", "qpid/common/util", "dojo/domReady!"], - function (registry, util) - { - return { - show: function(data) - { - util.parseHtmlIntoDiv(data.containerNode, "virtualhost/sizemonitoring/edit.html", - function() - { - registry.byId("editVirtualHost.storeUnderfullSize").set("regExpGen", util.numericOrContextVarRegexp); - registry.byId("editVirtualHost.storeOverfullSize").set("regExpGen", util.numericOrContextVarRegexp); - }); - } - }; - } -); diff --git a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhost/bdb/show.js b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhost/bdb/show.js deleted file mode 100644 index d7e84aa6a4..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhost/bdb/show.js +++ /dev/null @@ -1,38 +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. - */ - -define(["qpid/common/util", - "dojo/domReady!"], - function (util) - { - var fields = ["storePath", "storeUnderfullSize", "storeOverfullSize"]; - - function BDB(data) - { - util.buildUI(data.containerNode, data.parent, "virtualhost/sizemonitoring/show.html", fields, this); - } - - BDB.prototype.update = function(data) - { - util.updateUI(data, fields, this); - } - - return BDB; - } -); diff --git a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhost/bdb_ha/add.js b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhost/bdb_ha/add.js deleted file mode 100644 index 093f63af35..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhost/bdb_ha/add.js +++ /dev/null @@ -1,39 +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. - */ -define(["dojo/_base/xhr", - "dojo/parser", - "dojo/dom", - "dojo/dom-construct", - "dojo/json", - "dijit/registry", - "dojo/text!virtualhost/bdb_ha/add.html", - "dijit/form/ValidationTextBox", - "dijit/form/CheckBox", - "dojo/domReady!"], - function (xhr, parser, dom, domConstruct, json, registry, template) - { - return { - show: function(data) - { - this.containerNode = domConstruct.create("div", {innerHTML: template}, data.containerNode); - parser.parse(this.containerNode); - } - }; - } -); diff --git a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhost/bdb_ha/edit.js b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhost/bdb_ha/edit.js deleted file mode 100644 index ebe6b6822a..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhost/bdb_ha/edit.js +++ /dev/null @@ -1,34 +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. - */ -define(["qpid/common/util", "qpid/common/metadata", "dijit/registry", "dojo/domReady!"], - function (util, metadata, registry, win) - { - return { - show: function(data) - { - util.parseHtmlIntoDiv(data.containerNode, "virtualhost/bdb_ha/edit.html", - function() - { - registry.byId("editVirtualHost.storeUnderfullSize").set("regExpGen", util.numericOrContextVarRegexp); - registry.byId("editVirtualHost.storeOverfullSize").set("regExpGen", util.numericOrContextVarRegexp); - }); - } - }; - } -); diff --git a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhost/bdb_ha/show.js b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhost/bdb_ha/show.js deleted file mode 100644 index c0b079cf4c..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhost/bdb_ha/show.js +++ /dev/null @@ -1,75 +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. - */ - -define(["qpid/common/util", "dojo/query", "dojo/domReady!"], - function (util, query) - { - var localTransactionSynchronizationPolicy = "localTransactionSynchronizationPolicy"; - var remoteTransactionSynchronizationPolicy = "remoteTransactionSynchronizationPolicy"; - - var fields = [ "storeUnderfullSize", "storeOverfullSize"]; - - function BDB(data) - { - var that = this; - util.buildUI(data.containerNode, data.parent, "virtualhost/bdb_ha/show.html", fields, this, - function() - { - that[localTransactionSynchronizationPolicy]= query("." + localTransactionSynchronizationPolicy, data.containerNode)[0]; - that[remoteTransactionSynchronizationPolicy]= query("."+ remoteTransactionSynchronizationPolicy, data.containerNode)[0]; - }); - } - - BDB.prototype.update = function(data) - { - util.updateUI(data, fields, this); - - var localSyncPolicy = data[localTransactionSynchronizationPolicy] ? data[localTransactionSynchronizationPolicy].toLowerCase() : ""; - var remoteSyncPolicy = data[remoteTransactionSynchronizationPolicy] ? data[remoteTransactionSynchronizationPolicy].toLowerCase() : ""; - - for(var i=0; i<this[localTransactionSynchronizationPolicy].children.length;i++) - { - var child = this[localTransactionSynchronizationPolicy].children[i]; - if (child.className == localTransactionSynchronizationPolicy + "-" + localSyncPolicy) - { - child.style.display = "block"; - } - else - { - child.style.display = "none"; - } - } - - for(var j=0; j<this[remoteTransactionSynchronizationPolicy].children.length;j++) - { - var child = this[remoteTransactionSynchronizationPolicy].children[j]; - if (child.className == remoteTransactionSynchronizationPolicy + "-" + remoteSyncPolicy) - { - child.style.display = "block"; - } - else - { - child.style.display = "none"; - } - } - } - - return BDB; - } -); diff --git a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb/add.js b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb/add.js deleted file mode 100644 index 4053a1bb41..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb/add.js +++ /dev/null @@ -1,41 +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. - * - */ -define(["dojo/_base/xhr", - "dojo/parser", - "dojo/dom", - "dojo/dom-construct", - "dojo/json", - "dijit/registry", - "dojo/text!virtualhostnode/bdb/add.html", - "dijit/form/ValidationTextBox", - "dijit/form/CheckBox", - "dojo/domReady!"], - function (xhr, parser, dom, domConstruct, json, registry, template) - { - return { - show: function(data) - { - this.containerNode = domConstruct.create("div", {innerHTML: template}, data.containerNode); - parser.parse(this.containerNode); - } - }; - } -); diff --git a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb/edit.js b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb/edit.js deleted file mode 100644 index 4c70b4a22d..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb/edit.js +++ /dev/null @@ -1,33 +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. - */ -define(["qpid/common/util", "dijit/registry", "dojo/domReady!"], - function (util, registry) - { - return { - show: function(data) - { - util.parseHtmlIntoDiv(data.containerNode, "virtualhostnode/filebased/edit.html", - function() - { - registry.byId("editVirtualHostNode.storePath").set("disabled", !(data.data.state == "STOPPED" || data.data.state == "ERRORED")); - }); - } - }; - } -); diff --git a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb/show.js b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb/show.js deleted file mode 100644 index 6f4e167e72..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb/show.js +++ /dev/null @@ -1,38 +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. - * - */ -define(["qpid/common/util", "dojo/domReady!"], - function (util) - { - var fieldNames = ["storePath"]; - - function BdbNode(data) - { - this.parent = data.parent; - util.buildUI(data.containerNode, data.parent, "virtualhostnode/bdb/show.html", fieldNames, this); - } - - BdbNode.prototype.update=function(data) - { - util.updateUI(data, fieldNames, this); - }; - - return BdbNode; -}); diff --git a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add.js b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add.js deleted file mode 100644 index 9b2b26d560..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add.js +++ /dev/null @@ -1,82 +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. - * - */ -define(["dojo/_base/xhr", - "dojo/parser", - "dojo/_base/array", - "dojo/dom", - "dojo/dom-construct", - "dojo/json", - "dijit/registry", - "dojo/text!virtualhostnode/bdb_ha/add.html", - "dijit/form/ValidationTextBox", - "dijit/form/RadioButton", - "dojo/domReady!"], - function (xhr, parser, array, dom, domConstruct, json, registry, template) - { - return { - show: function(data) - { - var that=this; - - this.containerNode = domConstruct.create("div", {innerHTML: template}, data.containerNode); - parser.parse(this.containerNode).then(function(instances) - { - // lookup field - that.groupChoice = registry.byId("addVirtualHostNode.group"); - that.virtualHostNodeBdbhaTypeFieldsContainer = dom.byId("addVirtualHostNode.bdbha.typeFields"); - - // add callback - that.groupChoice.on("change", - function(type) - { - that._groupChoiceChanged(type, - that.virtualHostNodeBdbhaTypeFieldsContainer, - "qpid/management/virtualhostnode/bdb_ha/add/"); - }); - }); - }, - _groupChoiceChanged: function(type, typeFieldsContainer, urlStem) - { - var widgets = registry.findWidgets(typeFieldsContainer); - array.forEach(widgets, function(item) { item.destroyRecursive();}); - domConstruct.empty(typeFieldsContainer); - - if (type) - { - var that = this; - require([urlStem + type.toLowerCase() + "/add"], - function(TypeUI) - { - try - { - TypeUI.show({containerNode:typeFieldsContainer, parent: that}); - } - catch(e) - { - console.warn(e); - } - } - ); - } - } - }; - } -); diff --git a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/existinggroup/add.js b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/existinggroup/add.js deleted file mode 100644 index be43e5f28b..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/existinggroup/add.js +++ /dev/null @@ -1,48 +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. - */ -define(["dojo/_base/xhr", - "dojo/parser", - "dojo/dom", - "dojo/dom-construct", - "dojo/json", - "dijit/registry", - "dojo/text!virtualhostnode/bdb_ha/add/existinggroup/add.html", - "qpid/common/util", - "dijit/form/ValidationTextBox", - "dijit/form/CheckBox", - "dojo/domReady!"], - function (xhr, parser, dom, domConstruct, json, registry, template, util) - { - return { - show: function(data) - { - this.containerNode = domConstruct.create("div", {innerHTML: template}, data.containerNode); - parser.parse(this.containerNode).then(function(instances) - { - registry.byId("addVirtualHostNode.groupName").set("regExpGen", util.nameOrContextVarRegexp); - registry.byId("addVirtualHostNode.helperNodeName").set("regExpGen", util.nameOrContextVarRegexp); - registry.byId("addVirtualHostNode.helperAddress").set("regExpGen", util.nodeAddressOrContextVarRegexp); - registry.byId("addVirtualHostNode.address").set("regExpGen", util.nodeAddressOrContextVarRegexp); - - dom.byId("addVirtualHostNode.uploadFields").style.display = "none"; - }); - } - }; - } -); diff --git a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/newgroup/add.js b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/newgroup/add.js deleted file mode 100644 index 841f2051f5..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/newgroup/add.js +++ /dev/null @@ -1,185 +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. - */ -define(["dojo/_base/xhr", - "dojo/_base/window", - "dojo/parser", - "dojo/dom", - "dojo/dom-construct", - "dojo/json", - "dijit/registry", - "dojo/text!virtualhostnode/bdb_ha/add/newgroup/add.html", - "qpid/common/util", - "dijit/form/ValidationTextBox", - "dijit/form/MultiSelect", - "dijit/form/Button", - "dojo/domReady!"], - function (xhr, win, parser, dom, domConstruct, json, registry, template, util) - { - return { - show: function(data) - { - var that=this; - - this.containerNode = domConstruct.create("div", {innerHTML: template}, data.containerNode); - parser.parse(this.containerNode).then(function(instances) - { - that._postParse(data); - }); - - }, - _postParse: function(data) - { - var that=this; - this.addVirtualHostNodeAddress = registry.byId("addVirtualHostNode.address"); - this.addVirtualHostNodeAddress.set("regExpGen", util.nodeAddressOrContextVarRegexp); - - this.addVirtualHostNodeAddress.on("change", function(address){that._changeAddress(address, that.virtualHostNodeHelperAddress);}); - this.addVirtualHostNodeAddress.on("click", function(e){that._updatePermittedNodesJson();}); - - this.virtualHostNodeHelperAddress = registry.byId("addVirtualHostNode.helperAddress"); - this.virtualHostNodeHelperAddress.set("regExpGen", util.nodeAddressOrContextVarRegexp); - - // list objects html node and dojo object - this.addVirtualHostNodePermittedNodesList = dom.byId("addVirtualHostNode.permittedNodesList"); - this.addVirtualHostNodePermittedNodesListDojo = registry.byId("addVirtualHostNode.permittedNodesList"); - this.addVirtualHostNodePermittedNodesListDojo.on("change", function(value){that._changePermittedNodeList(value);}); - - // permitted node text field - this.addVirtualHostNodePermittedNode = registry.byId("addVirtualHostNode.permittedNode"); - this.addVirtualHostNodePermittedNode.set("regExpGen", util.nodeAddressOrContextVarRegexp); - this.addVirtualHostNodePermittedNode.on("change", function(value){that._changePermittedNode(value);}); - - // add and remove buttons & click handlers - this.addVirtualHostNodePermittedNodeAddButton = registry.byId("addVirtualHostNode.permittedNodeAdd"); - this.addVirtualHostNodePermittedNodeAddButton.set("disabled", true); - this.addVirtualHostNodePermittedNodeRemoveButton = registry.byId("addVirtualHostNode.permittedNodeRemove"); - this.addVirtualHostNodePermittedNodeRemoveButton.set("disabled", true); - this.addVirtualHostNodePermittedNodeAddButton.on("click", function(e){that._clickAddPermittedNodeButton(e);}); - this.addVirtualHostNodePermittedNodeRemoveButton.on("click", function(e){that._clickRemovePermittedNodeButton(e);}); - - // This will contain the serialised form that will go to the server - this.addVirtualHostNodePermittedNodes = registry.byId("addVirtualHostNode.permittedNodes"); - - registry.byId("addVirtualHostNode.groupName").set("regExpGen", util.nameOrContextVarRegexp); - - dom.byId("addVirtualHostNode.uploadFields").style.display = "block"; - }, - _updatePermittedNodesJson: function () - { - var nodeAddress = this.addVirtualHostNodeAddress.get("value"); - var permittedNodes = [ ]; - if (nodeAddress) - { - permittedNodes.push(nodeAddress); - } - var children = this.addVirtualHostNodePermittedNodesList.children; - var i; - for (i = 0; i < children.length; i++) - { - var child = children.item(i); - if (child.value != nodeAddress) - { - permittedNodes.push(child.value); - } - } - - this.addVirtualHostNodePermittedNodes.set("value", permittedNodes); - }, - _changePermittedNodeList: function(value) - { - var hasSelection = this.addVirtualHostNodePermittedNodesListDojo.get("value").length > 0; - this.addVirtualHostNodePermittedNodeRemoveButton.set("disabled", !hasSelection); - }, - _changePermittedNode: function(value) - { - var fieldIsEmpty = (this.addVirtualHostNodePermittedNode.get("value") == ""); - this.addVirtualHostNodePermittedNodeAddButton.set("disabled", fieldIsEmpty); - return true; - }, - _changeAddress: function(address, virtualHostNodeHelperAddress) - { - virtualHostNodeHelperAddress.set("value", address); - this._updatePermittedNodesJson(); - }, - _clickAddPermittedNodeButton: function(e) - { - // check the text box is valid and not empty - if(this.addVirtualHostNodePermittedNode.isValid() && - this.addVirtualHostNodePermittedNode.value && - this.addVirtualHostNodePermittedNode.value != "") - { - // read value to add from text box - var newAddress = this.addVirtualHostNodePermittedNode.value; - - // clear UI value - this.addVirtualHostNodePermittedNode.set("value", ""); - this.addVirtualHostNodePermittedNodeAddButton.set("disabled", true); - - //check entry not already present in list - var alreadyPresent = false; - var children = this.addVirtualHostNodePermittedNodesList.children; - var i; - for (i = 0; i < children.length; i++) - { - var child = children.item(i); - if (child.value == newAddress) - { - alreadyPresent = true; - break; - } - } - - if (!alreadyPresent) - { - // construct new option for list - var newOption = win.doc.createElement('option'); - newOption.innerHTML = newAddress; - newOption.value = newAddress; - - // add new option to list - this.addVirtualHostNodePermittedNodesList.appendChild(newOption); - } - } - this._updatePermittedNodesJson(); - }, - _clickRemovePermittedNodeButton: function(e) - { - var selectedValues = this.addVirtualHostNodePermittedNodesListDojo.get("value"); - var v; - for (v in selectedValues) - { - var children = this.addVirtualHostNodePermittedNodesList.children; - var i; - for (i = 0; i < children.length; i++) - { - var child = children.item(i); - if (child.value == selectedValues[v]) - { - this.addVirtualHostNodePermittedNodesList.removeChild(child); - } - } - } - this.addVirtualHostNodePermittedNodeRemoveButton.set("disabled", true); - - this._updatePermittedNodesJson(); - - } - }; - } -); diff --git a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/edit.js b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/edit.js deleted file mode 100644 index e3d69577dc..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/edit.js +++ /dev/null @@ -1,184 +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. - * - */ -define(["qpid/common/util", - "dijit/registry", - "dojo/store/Memory", - "dojo/data/ObjectStore", - "dojo/_base/window", - "dojo/domReady!"], - function (util, registry, Memory, ObjectStore, win) - { - return { - show: function(data) - { - var that = this; - util.parseHtmlIntoDiv(data.containerNode, "virtualhostnode/bdb_ha/edit.html", - function(){that._postParse(data);}); - }, - _postParse: function(data) - { - var node = data.data; - if ( !(data.data.state == "ERRORED" || data.data.state == "STOPPED")) - { - registry.byId("editVirtualHostNode.storePath").set("disabled", true); - } - if (!( data.effectiveData.role == "MASTER" || data.data.state == "ERRORED" || data.data.state == "STOPPED")) - { - registry.byId("editVirtualHostNode.permittedNodesList").set("disabled", true); - } - var overrideData = [{id: '0', name: 'Majority', selected: '1'}]; - if (node.remotereplicationnodes && node.remotereplicationnodes.length>1) - { - registry.byId("editVirtualHostNode.designatedPrimary").set("disabled", true); - registry.byId("editVirtualHostNode.priority").set("disabled", false); - registry.byId("editVirtualHostNode.quorumOverride").set("disabled", false); - var overrideLimit = Math.floor((node.remotereplicationnodes.length + 1)/2); - for(var i = 1; i <= overrideLimit; i++) - { - overrideData.push({id: i, name: i + ""}); - } - } - else - { - registry.byId("editVirtualHostNode.designatedPrimary").set("disabled", false); - registry.byId("editVirtualHostNode.priority").set("disabled", true); - registry.byId("editVirtualHostNode.quorumOverride").set("disabled", true); - } - var store = new Memory({data :overrideData, idProperty: "id" }); - registry.byId("editVirtualHostNode.quorumOverride").set("store", new ObjectStore({objectStore: store})); - - var that = this; - this.permittedNodes = registry.byId("editVirtualHostNode.permittedNodes"); - this.permittedNodesList = registry.byId("editVirtualHostNode.permittedNodesList"); - this.permittedNodesList.on("change", function(value){that._changePermittedNodeList(value);}); - - // permitted node text field - this.permittedNode = registry.byId("editVirtualHostNode.permittedNode"); - this.permittedNode.on("change", function(value){that._changePermittedNode(value);}); - - // add and remove buttons & click handlers - this.permittedNodeAddButton = registry.byId("editVirtualHostNode.permittedNodeAdd"); - this.permittedNodeAddButton.set("disabled", true); - this.permittedNodeRemoveButton = registry.byId("editVirtualHostNode.permittedNodeRemove"); - this.permittedNodeRemoveButton.set("disabled", true); - this.permittedNodeAddButton.on("click", function(e){that._clickAddPermittedNodeButton(e);}); - this.permittedNodeRemoveButton.on("click", function(e){that._clickRemovePermittedNodeButton(e);}); - - var permittedNodes = data.data.permittedNodes; - for(var i=0; i<permittedNodes.length;i++) - { - var host = permittedNodes[i]; - var newOption = this._addOption(host); - // add new option to list - this.permittedNodesList.containerNode.appendChild(newOption); - } - }, - _clickAddPermittedNodeButton: function(e) - { - // check the text box is valid and not empty - if(this.permittedNode.isValid() && - this.permittedNode.value && - this.permittedNode.value != "") - { - // read value to add from text box - var newAddress = this.permittedNode.value; - - // clear UI value - this.permittedNode.set("value", ""); - this.permittedNodeAddButton.set("disabled", true); - - //check entry not already present in list - var alreadyPresent = false; - var children = this.permittedNodesList.containerNode.children; - var i; - for (i = 0; i < children.length; i++) - { - var child = children.item(i); - if (child.value == newAddress) - { - alreadyPresent = true; - break; - } - } - - if (!alreadyPresent) - { - var newOption = this._addOption(newAddress); - - // add new option to list - this.permittedNodesList.containerNode.appendChild(newOption); - this._updatePermittedNodes(); - } - } - }, - _clickRemovePermittedNodeButton: function(e) - { - var selectedValues = this.permittedNodesList.get("value"); - var v; - for (v in selectedValues) - { - var children = this.permittedNodesList.containerNode.children; - var i; - for (i = 0; i < children.length; i++) - { - var child = children.item(i); - if (child.value == selectedValues[v]) - { - this.permittedNodesList.containerNode.removeChild(child); - } - } - } - this._updatePermittedNodes(); - this.permittedNodeRemoveButton.set("disabled", true); - }, - _addOption: function(newAddress) - { - // construct new option for list - var newOption = win.doc.createElement('option'); - newOption.innerHTML = newAddress; - newOption.value = newAddress; - return newOption; - }, - _changePermittedNodeList: function(value) - { - var hasSelection = this.permittedNodesList.get("value").length > 0; - this.permittedNodeRemoveButton.set("disabled", !hasSelection); - }, - _changePermittedNode: function(value) - { - var fieldIsEmpty = (this.permittedNode.get("value") == ""); - this.permittedNodeAddButton.set("disabled", fieldIsEmpty); - return true; - }, - _updatePermittedNodes: function() - { - var values = []; - var children = this.permittedNodesList.containerNode.children; - for (var i = 0; i < children.length; i++) - { - var child = children.item(i); - values.push(children.item(i).value); - } - this.permittedNodes.set("value", values); - } - }; - } -); diff --git a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/show.js b/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/show.js deleted file mode 100644 index 5338916812..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/show.js +++ /dev/null @@ -1,241 +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. - * - */ -define(["dojo/_base/xhr", - "dojo/_base/connect", - "dojox/html/entities", - "dojo/query", - "dojo/json", - "dijit/registry", - "dojox/grid/EnhancedGrid", - "qpid/common/UpdatableStore", - "qpid/management/UserPreferences", - "qpid/common/util", - "dojo/domReady!"], - function (xhr, connect, entities, query, json, registry, EnhancedGrid, UpdatableStore, UserPreferences, util) - { - var priorityNames = {'_0': 'Never', '_1': 'Default', '_2': 'High', '_3': 'Highest'}; - var nodeFields = ["storePath", "groupName", "role", "address", "designatedPrimary", "priority", "quorumOverride"]; - - function findNode(nodeClass, containerNode) - { - return query("." + nodeClass, containerNode)[0]; - } - - function sendRequest(nodeName, remoteNodeName, method, attributes) - { - var success = false; - var failureReason = ""; - var url = null; - if (nodeName == remoteNodeName) - { - url = "api/latest/virtualhostnode/" + encodeURIComponent(nodeName); - } - else - { - url = "api/latest/replicationnode/" + encodeURIComponent(nodeName) + "/" + encodeURIComponent(remoteNodeName); - } - - if (method == "POST") - { - xhr.put({ - url: url, - sync: true, - handleAs: "json", - headers: { "Content-Type": "application/json"}, - putData: json.stringify(attributes), - load: function(x) {success = true; }, - error: function(error) {success = false; failureReason = error;} - }); - } - else if (method == "DELETE") - { - xhr.del({url: url, sync: true, handleAs: "json"}).then( - function(data) { success = true; }, - function(error) {success = false; failureReason = error;} - ); - } - - if (!success) - { - util.xhrErrorHandler(failureReason); - } - return success; - } - - function BDBHA(data) - { - this.parent = data.parent; - var that = this; - util.buildUI(data.containerNode, data.parent, "virtualhostnode/bdb_ha/show.html", nodeFields, this, function(){that._postParse(data);}); - }; - BDBHA.prototype._postParse = function(data) - { - var that = this; - var containerNode = data.containerNode; - this.designatedPrimaryContainer = findNode("designatedPrimaryContainer", containerNode); - this.priorityContainer = findNode("priorityContainer", containerNode); - this.quorumOverrideContainer = findNode("quorumOverrideContainer", containerNode); - this.permittedNodes = query(".permittedNodes", containerNode)[0]; - this.membersGridPanel = registry.byNode(query(".membersGridPanel", containerNode)[0]); - this.membersGrid = new UpdatableStore([], - findNode("groupMembers", containerNode), - [ - { name: 'Name', field: 'name', width: '10%' }, - { name: 'Role', field: 'role', width: '15%' }, - { name: 'Address', field: 'address', width: '30%' }, - { name: 'Join Time', field: 'joinTime', width: '25%', formatter: function(value){ return value ? UserPreferences.formatDateTime(value) : "";} }, - { name: 'Replication Transaction ID', field: 'lastKnownReplicationTransactionId', width: '20%', formatter: function(value){ return value > 0 ? value : "N/A";} } - ], - null, - { - selectionMode: "single", - keepSelection: true, - plugins: { - indirectSelection: true - } - }, - EnhancedGrid, true ); - - this.removeNodeButton = registry.byNode(query(".removeNodeButton", containerNode)[0]); - this.transferMasterButton = registry.byNode(query(".transferMasterButton", containerNode)[0]); - this.transferMasterButton.set("disabled", true); - this.removeNodeButton.set("disabled", true); - - var nodeControlsToggler = function(rowIndex) - { - var data = that.membersGrid.grid.selection.getSelected(); - that.transferMasterButton.set("disabled", data.length != 1|| data[0].role != "REPLICA"); - that.removeNodeButton.set("disabled", data.length != 1 || data[0].role == "MASTER"); - }; - connect.connect(this.membersGrid.grid.selection, 'onSelected', nodeControlsToggler); - connect.connect(this.membersGrid.grid.selection, 'onDeselected', nodeControlsToggler); - - this.transferMasterButton.on("click", - function(e) - { - var data = that.membersGrid.grid.selection.getSelected(); - if (data.length == 1 && confirm("Are you sure you would like to transfer mastership to node '" + data[0].name + "'?")) - { - sendRequest(that.data.name, data[0].name, "POST", {role: "MASTER"}); - that.membersGrid.grid.selection.clear(); - } - } - ); - - this.removeNodeButton.on("click", - function(e){ - var data = that.membersGrid.grid.selection.getSelected(); - if (data.length == 1 && confirm("Are you sure you would like to delete node '" + data[0].name + "'?")) - { - if (sendRequest(that.data.name, data[0].name, "DELETE")) - { - that.membersGrid.grid.selection.clear(); - if (data[0].name == that.data.name) - { - that.parent.destroy(); - } - } - } - } - ); - } - - BDBHA.prototype.update=function(data) - { - this.parent.editNodeButton.set("disabled", false); - - - var permittedNodesMarkup = ""; - if (data.permittedNodes) - { - for(var i=0;i<data.permittedNodes.length;i++) - { - permittedNodesMarkup+="<div>" + data.permittedNodes[i] + "</div>"; - } - } - this.permittedNodes.innerHTML = permittedNodesMarkup ; - - this.data = data; - for(var i = 0; i < nodeFields.length; i++) - { - var name = nodeFields[i]; - if (name == "priority") - { - this[name].innerHTML = priorityNames["_" + data[name]]; - } - else if (name == "quorumOverride") - { - this[name].innerHTML = (data[name] == 0 ? "MAJORITY" : entities.encode(String(data[name]))); - } - else - { - this[name].innerHTML = entities.encode(String(data[name])); - } - } - - var members = data.remotereplicationnodes; - if (members) - { - members.push({ - id: data.id, - name: data.name, - groupName: data.groupName, - address: data.address, - role: data.role, - joinTime: data.joinTime, - lastKnownReplicationTransactionId: data.lastKnownReplicationTransactionId - }); - } - this._updateGrid(members, this.membersGridPanel, this.membersGrid); - - if (!members || members.length < 3) - { - this.designatedPrimaryContainer.style.display="block"; - this.priorityContainer.style.display="none"; - this.quorumOverrideContainer.style.display="none"; - } - else - { - this.designatedPrimaryContainer.style.display="none"; - this.priorityContainer.style.display="block"; - this.quorumOverrideContainer.style.display="block"; - } - }; - - BDBHA.prototype._updateGrid=function(conf, panel, updatableGrid) - { - if (conf && conf.length > 0) - { - panel.domNode.style.display="block"; - var changed = updatableGrid.update(conf); - if (changed) - { - updatableGrid.grid._refresh(); - } - } - else - { - panel.domNode.style.display="none"; - } - } - - return BDBHA; -}); diff --git a/qpid/java/bdbstore/src/main/java/resources/virtualhost/bdb_ha/add.html b/qpid/java/bdbstore/src/main/java/resources/virtualhost/bdb_ha/add.html deleted file mode 100644 index d82f8108ee..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/virtualhost/bdb_ha/add.html +++ /dev/null @@ -1,20 +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. - --> -<div> - <div class="clear"></div> - <div class="infoMessage">The virtualhost will have the same name as the group.</div> -</div> diff --git a/qpid/java/bdbstore/src/main/java/resources/virtualhost/bdb_ha/edit.html b/qpid/java/bdbstore/src/main/java/resources/virtualhost/bdb_ha/edit.html deleted file mode 100644 index 64cef941e2..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/virtualhost/bdb_ha/edit.html +++ /dev/null @@ -1,94 +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. - --> -<div> - - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Store overfull size (bytes):</div> - <div class="tableContainer-valueCell formLabel-controlCell"> - <input data-dojo-type="dijit/form/ValidationTextBox" - id="editVirtualHost.storeOverfullSize" - data-dojo-props=" - name: 'storeOverfullSize', - placeHolder: 'size in bytes', - required: false, - title: 'Enter ceiling (in bytes) at which store will begin to throttle sessions producing messages', - promptMessage: 'Ceiling (in bytes) at which store will begin to throttle sessions producing messages'"/> - </div> - </div> - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Store underfull size (bytes):</div> - <div class="tableContainer-valueCell formLabel-controlCell"> - <input data-dojo-type="dijit/form/ValidationTextBox" - id="editVirtualHost.storeUnderfullSize" - data-dojo-props=" - name: 'storeUnderfullSize', - placeHolder: 'size in bytes', - required: false, - title: 'Enter floor (in bytes) at which store will cease to throttle sessions producing messages', - promptMessage: 'Floor (in bytes) at which store will cease to throttle sessions producing messages'"/> - </div> - </div> - - - <div class="clear"></div> - - <div class="formBox clear"> - <fieldset> - <legend>High availability durability</legend> - <div> - <div class="haOptionLabel">Master transaction sync policy</div> - - <span id="editVirtualHost.localTransactionSynchronizationPolicy.span"> - <select id="editVirtualHost.localTransactionSynchronizationPolicy" - name="localTransactionSynchronizationPolicy" - data-dojo-type="dojox/form/CheckedMultiSelect"> - <option value="SYNC">SYNC (the transaction will be written and synchronized to the disk; highest durability)</option> - <option value="WRITE_NO_SYNC">WRITE_NO_SYNC (the transaction will be written only; the synchronization will be performed later)</option> - <option value="NO_SYNC">NO_SYNC (write later; the transaction will be written and synchronized later; lowest durability)</option> - </select> - </span> - <div id="editVirtualHost.localTransactionSynchronizationPolicy.tooltip" - data-dojo-type="dijit/Tooltip" - data-dojo-props="connectId: ['editVirtualHost.localTransactionSynchronizationPolicy', 'editVirtualHost.localTransactionSynchronizationPolicy.span'], - label: 'Synchronization policy applied at a node that is currently a master'"> - </div> - </div> - <br/> - <div> - <div class="haOptionLabel">Replica transaction sync policy</div> - - <span id="editVirtualHost.remoteTransactionSynchronizationPolicy.span"> - <select id="editVirtualHost.remoteTransactionSynchronizationPolicy" - name="remoteTransactionSynchronizationPolicy" - data-dojo-type="dojox/form/CheckedMultiSelect"> - <option value="SYNC">SYNC (the transaction will be written and synchronized to the disk; highest durability)</option> - <option value="WRITE_NO_SYNC">WRITE_NO_SYNC (the transaction will be written only; the synchronization will be performed later)</option> - <option value="NO_SYNC">NO_SYNC (write later; the transaction will be written and synchronized later; lowest durability)</option> - </select> - </span> - <div id="editVirtualHost.remoteTransactionSynchronizationPolicy.tooltip" - data-dojo-type="dijit/Tooltip" - data-dojo-props="connectId: ['editVirtualHost.remoteTransactionSynchronizationPolicy', 'editVirtualHost.remoteTransactionSynchronizationPolicy.span'], - label: 'Synchronization policy applied at a node that is currently a replica'"> - </div> - </div> - </fieldset> - </div> - -</div> diff --git a/qpid/java/bdbstore/src/main/java/resources/virtualhost/bdb_ha/show.html b/qpid/java/bdbstore/src/main/java/resources/virtualhost/bdb_ha/show.html deleted file mode 100644 index d96942cd2d..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/virtualhost/bdb_ha/show.html +++ /dev/null @@ -1,51 +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. - --> - -<div> - <div class="clear"> - <div class="formLabel-labelCell">Store overfull size:</div> - <div><span class="storeOverfullSize" ></span> bytes</div> - </div> - <div class="clear"> - <div class="formLabel-labelCell">Store underfull size:</div> - <div><span class="storeUnderfullSize"></span> bytes</div> - </div> - <div class="clear"></div> - <br/> - - <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'High Availability Durability', open: true"> - <div class="clear"> - <div class="formLabel-labelCell">Master transaction sync policy:</div> - <div class="localTransactionSynchronizationPolicy"> - <span class="localTransactionSynchronizationPolicy-sync">SYNC (the transaction will be written and synchronized to the disk; highest durability)</span> - <span class="localTransactionSynchronizationPolicy-write_no_sync">WRITE_NO_SYNC (the transaction will be written only; the synchronization will be performed later)</span> - <span class="localTransactionSynchronizationPolicy-no_sync">NO_SYNC (write later; the transaction will be written and synchronized later; lowest durability)</span> - </div> - </div> - <div class="clear"> - <div class="formLabel-labelCell">Replica transaction sync policy:</div> - <div class="remoteTransactionSynchronizationPolicy"> - <span class="remoteTransactionSynchronizationPolicy-sync">SYNC (the transaction will be written and synchronized to the disk; highest durability)</span> - <span class="remoteTransactionSynchronizationPolicy-write_no_sync">WRITE_NO_SYNC (the transaction will be written only; the synchronization will be performed later)</span> - <span class="remoteTransactionSynchronizationPolicy-no_sync">NO_SYNC (write later; the transaction will be written and synchronized later; lowest durability)</span> - </div> - </div> - </div> - -</div> diff --git a/qpid/java/bdbstore/src/main/java/resources/virtualhostnode/bdb/add.html b/qpid/java/bdbstore/src/main/java/resources/virtualhostnode/bdb/add.html deleted file mode 100644 index c16dd675d2..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/virtualhostnode/bdb/add.html +++ /dev/null @@ -1,36 +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. - - - --> -<div> - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Store path:</div> - <div class="formLabel-controlCell tableContainer-valueCell"> - <input type="text" id="addVirtualHostNode.storePath" - data-dojo-type="dijit/form/ValidationTextBox" - data-dojo-props=" - name: 'storePath', - placeHolder: 'path/to/store', - title: 'Enter store path', - promptMessage: 'File system location for the configuration store.'"/> - </div> - </div> - - <div class="clear"></div> -</div> diff --git a/qpid/java/bdbstore/src/main/java/resources/virtualhostnode/bdb/show.html b/qpid/java/bdbstore/src/main/java/resources/virtualhostnode/bdb/show.html deleted file mode 100644 index 09fcab4b1c..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/virtualhostnode/bdb/show.html +++ /dev/null @@ -1,23 +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. - --> -<div> - <div class="clear"> - <div class="formLabel-labelCell">Configuration store path:</div> - <div class="storePath"></div> - </div> - <div class="clear"></div> -</div> diff --git a/qpid/java/bdbstore/src/main/java/resources/virtualhostnode/bdb_ha/add.html b/qpid/java/bdbstore/src/main/java/resources/virtualhostnode/bdb_ha/add.html deleted file mode 100644 index 6973cf9002..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/virtualhostnode/bdb_ha/add.html +++ /dev/null @@ -1,44 +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. - - - --> -<div> - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Create new group or join existing group*:</div> - <div class="formLabel-controlCell tableContainer-valueCell"> - <div> - - <div data-dojo-type="dojo/store/Memory" - data-dojo-id="groupStore" - data-dojo-props="data: [{id: 'newgroup', name: 'New Group'}, {id: 'existinggroup', name: 'Existing Group'}]"></div> - <input data-dojo-type="dijit/form/FilteringSelect" - data-dojo-props="store:groupStore, - searchAttr:'name', - required: true, - placeHolder: 'choose new or existing', - promptMessage: 'Create a new group or join to an existing one', - title: 'Choose whether to create a new group or join to an existing one'" - name="group" - id="addVirtualHostNode.group" /> - </div> - </div> - </div> - <div class="clear"></div> - <div id="addVirtualHostNode.bdbha.typeFields"></div> -</div> diff --git a/qpid/java/bdbstore/src/main/java/resources/virtualhostnode/bdb_ha/add/existinggroup/add.html b/qpid/java/bdbstore/src/main/java/resources/virtualhostnode/bdb_ha/add/existinggroup/add.html deleted file mode 100644 index d8f1ae5c57..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/virtualhostnode/bdb_ha/add/existinggroup/add.html +++ /dev/null @@ -1,98 +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. - --> -<div> - - <div class="formBox"> - <fieldset> - <legend>Existing details</legend> - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Group name*:</div> - <div class="formLabel-controlCell tableContainer-valueCell"> - <input type="text" id="addVirtualHostNode.groupName" - data-dojo-type="dijit/form/ValidationTextBox" - data-dojo-props=" - name: 'groupName', - placeHolder: 'group name', - required: true, - promptMessage: 'Name of the existing group', - title: 'Enter name of the existing group'," /> - </div> - </div> - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Node name from group*:</div> - <div class="formLabel-controlCell tableContainer-valueCell"> - <input type="text" id="addVirtualHostNode.helperNodeName" - data-dojo-type="dijit/form/ValidationTextBox" - data-dojo-props=" - name: 'helperNodeName', - placeHolder: 'node name from group', - required: true, - promptMessage: 'Node name of an existing group member.', - title: 'Enter node name of an existing member of the group'" /> - </div> - </div> - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Node address of same node*:</div> - <div class="formLabel-controlCell tableContainer-valueCell"> - <input type="text" id="addVirtualHostNode.helperAddress" - data-dojo-type="dijit/form/ValidationTextBox" - data-dojo-props=" - name: 'helperAddress', - placeHolder: 'node address from group', - required: true, - promptMessage: 'Node address of the existing group member.', - title: 'Enter node address of the existing group member'" /> - </div> - </div> - </fieldset> - </div> - - - <div class="formBox"> - <fieldset> - <legend>New node details</legend> - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Address*:</div> - <div class="formLabel-controlCell tableContainer-valueCell"> - <input type="text" id="addVirtualHostNode.address" - data-dojo-type="dijit/form/ValidationTextBox" - data-dojo-props=" - name: 'address', - placeHolder: 'host:port', - required: true, - promptMessage: 'Node hostname and port number that new node will use.<br/>Other nodes will use connect to this address to replicate messages', - title: 'Enter node hostname and port number that new node will use'" /> - </div> - </div> - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Store path:</div> - <div class="formLabel-controlCell tableContainer-valueCell"> - <input type="text" id="addVirtualHostNode.storePath" - data-dojo-type="dijit/form/ValidationTextBox" - data-dojo-props=" - name: 'storePath', - placeHolder: 'path/to/store', - promptMessage: 'File system location for the store', - title: 'Enter file system location for the store'" /> - </div> - </div> - </fieldset> - </div> - <div class="clear"></div> -</div> diff --git a/qpid/java/bdbstore/src/main/java/resources/virtualhostnode/bdb_ha/add/newgroup/add.html b/qpid/java/bdbstore/src/main/java/resources/virtualhostnode/bdb_ha/add/newgroup/add.html deleted file mode 100644 index 47df5e5155..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/virtualhostnode/bdb_ha/add/newgroup/add.html +++ /dev/null @@ -1,109 +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. - --> -<div> - - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Group name*:</div> - <div class="formLabel-controlCell tableContainer-valueCell"> - <input type="text" id="addVirtualHostNode.groupName" - data-dojo-type="dijit/form/ValidationTextBox" - data-dojo-props=" - name: 'groupName', - placeHolder: 'group name', - required: true, - title: 'Enter name to identify the new group', - promptMessage: 'Name to identify the new group.'"/> - </div> - </div> - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Address*:</div> - <div class="formLabel-controlCell tableContainer-valueCell"> - <input type="text" id="addVirtualHostNode.address" - data-dojo-type="dijit/form/ValidationTextBox" - data-dojo-props=" - name: 'address', - placeHolder: 'host:port', - required: true, - title: 'Enter node hostname and port number that new node will use', - promptMessage: 'Node hostname and port number that new node will use.<br/>Other nodes will use connect to this address to replicate messages'" /> - </div> - </div> - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Store path:</div> - <div class="formLabel-controlCell tableContainer-valueCell"> - <input type="text" id="addVirtualHostNode.storePath" - data-dojo-type="dijit/form/ValidationTextBox" - data-dojo-props=" - name: 'storePath', - placeHolder: 'path/to/store', - title: 'Enter file system location for the store', - promptMessage: 'File system location for the store'" /> - </div> - </div> - <div class="clear formBox"> - <fieldset> - <legend>Permitted group nodes</legend> - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Permitted addresses*:</div> - <div class="formLabel-controlCell tableContainer-valueCell addPermittedNodeList"> - <select type="text" id="addVirtualHostNode.permittedNodesList" - data-dojo-type="dijit/form/MultiSelect" - data-dojo-props=" - name: 'permittedNodesList', - readOnly : 'true', - title: 'Enter list of the other node address that will form the group'"> - </select> <!-- must use closing tag rather than shorthand - dojo bug? --> - </div> - <div id="addVirtualHostNode.permittedNodesList.tooltip" - data-dojo-type="dijit/Tooltip" - data-dojo-props="connectId: 'addVirtualHostNode.permittedNodesList', - label: 'Only node addresses appearing in the list will be permitted to join the group.'"> - </div> - <button data-dojo-type="dijit/form/Button" id="addVirtualHostNode.permittedNodeRemove" data-dojo-props="label: '-'" ></button> - </div> - - <div class="clear"></div> - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Address:</div> - <div class="formLabel-controlCell tableContainer-valueCell"> - <input type="text" id="addVirtualHostNode.permittedNode" - data-dojo-type="dijit/form/ValidationTextBox" - data-dojo-props=" - name: 'permittedNode', - placeHolder: 'host:port', - intermediateChanges: true, - title: 'Enter address of node to be permitted into the group', - promptMessage: 'Address of node to be permitted into the group'" /> - </div> - <button data-dojo-type="dijit/form/Button" id="addVirtualHostNode.permittedNodeAdd" data-dojo-props="label: '+'"></button> - </div> - </fieldset> - </div> - - <input type="hidden" id="addVirtualHostNode.permittedNodes" - data-dojo-type="dijit/form/ValidationTextBox" - data-dojo-props="name: 'permittedNodes'" - /> - - <input type="hidden" id="addVirtualHostNode.helperAddress" - data-dojo-type="dijit/form/ValidationTextBox" - data-dojo-props="name: 'helperAddress'" /> - - <div class="clear"></div> -</div> diff --git a/qpid/java/bdbstore/src/main/java/resources/virtualhostnode/bdb_ha/edit.html b/qpid/java/bdbstore/src/main/java/resources/virtualhostnode/bdb_ha/edit.html deleted file mode 100644 index cfff12dcf2..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/virtualhostnode/bdb_ha/edit.html +++ /dev/null @@ -1,152 +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. - --> -<div> - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Replication Group*:</div> - <div class="formLabel-controlCell tableContainer-valueCell"> - <input type="text" id="editVirtualHostNode.groupName" - data-dojo-type="dijit/form/ValidationTextBox" - data-dojo-props=" - name: 'groupName', - placeHolder: 'Group Name', - required: true, - disabled: true, - title: 'Name of the group'" /> - </div> - </div> - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Address*:</div> - <div class="formLabel-controlCell tableContainer-valueCell"> - <input type="text" id="editVirtualHostNode.address" - data-dojo-type="dijit/form/ValidationTextBox" - data-dojo-props=" - name: 'address', - placeHolder: 'host:port', - required: true, - disabled: true, - title: 'Node address of the group member'" /> - </div> - </div> - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Configuration store path:</div> - <div class="formLabel-controlCell tableContainer-valueCell"> - <input type="text" id="editVirtualHostNode.storePath" - data-dojo-type="dijit/form/ValidationTextBox" - data-dojo-props=" - name: 'storePath', - title: 'File system location for the store', - promptMessage: 'File system location for the store'" /> - - </div> - </div> - - <div class="formBox clear"> - <fieldset> - <legend>Permitted group nodes</legend> - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Permitted addresses*:</div> - <div class="formLabel-controlCell tableContainer-valueCell addPermittedNodeList"> - <select type="text" id="editVirtualHostNode.permittedNodesList" - data-dojo-type="dijit/form/MultiSelect" - data-dojo-props=" - multiple: true, - name: 'permittedNodeList', - readOnly : 'true', - excluded: true, - title: 'Enter permitted nodes'"> - </select> <!-- must use closing tag rather than shorthand - dojo bug? --> - <input type="hidden" id="editVirtualHostNode.permittedNodes" - data-dojo-type="dijit/form/ValidationTextBox" - name="permittedNodes"/> - </div> - <div id="editVirtualHostNode.permittedNodesList.tooltip" - data-dojo-type="dijit/Tooltip" - data-dojo-props="connectId: 'editVirtualHostNode.permittedNodesList', - label: 'Only node addresses appearing in the list will be permitted to join the group.'"> - </div> - <button data-dojo-type="dijit/form/Button" id="editVirtualHostNode.permittedNodeRemove" data-dojo-props="label: '-'" ></button> - </div> - - <div class="clear"></div> - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Address:</div> - <div class="formLabel-controlCell tableContainer-valueCell"> - <input type="text" id="editVirtualHostNode.permittedNode" - data-dojo-type="dijit/form/ValidationTextBox" - data-dojo-props=" - name: 'permittedNode', - placeHolder: 'host:port', - intermediateChanges: true, - title: 'Enter address of node to be permitted into the group', - promptMessage: 'Address of node to be permitted into the group'" /> - </div> - <button data-dojo-type="dijit/form/Button" id="editVirtualHostNode.permittedNodeAdd" data-dojo-props="label: '+'"></button> - </div> - </fieldset> - </div> - - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Allow this node to operate solo: </div> - <div class="formLabel-controlCell tableContainer-valueCell"> - <input type="checkbox" id="editVirtualHostNode.designatedPrimary" checked="checked" - data-dojo-type="dijit/form/CheckBox" - data-dojo-props=" - name: 'designatedPrimary', - required: false, - title: 'Designate node as primary allowing it to operate solo in a group of two.', - promptMessage: 'Designate node as primary allowing it to operate solo operate solo in a group of two'" /> - </div> - </div> - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Election priority of this node: </div> - <div class="formLabel-controlCell tableContainer-valueCell"> - <div data-dojo-type="dojo/store/Memory" data-dojo-id="nodePriorityStore" - data-dojo-props="data: [ - {id: '0', name: 'Never'}, - {id: '1', name: 'Default'}, - {id: '2', name: 'High'}, - {id: '3', name: 'Highest'} - ]"></div> - <input id="editVirtualHostNode.priority" data-dojo-type="dijit/form/FilteringSelect" - data-dojo-props=" - name: 'priority', - required: false, - store: nodePriorityStore, - title: 'Set the election priority associated with this node', - promptMessage: 'Election priority associated with this node.<br/>Elections will choose the node with the most recent transactions.<br/>If there is a tie, priority is used as a tie-breaker.', - searchAttr: 'name'" /> - </div> - </div> - <div class="clear"> - <div class="formLabel-labelCell tableContainer-labelCell">Required minimum number of nodes: </div> - <div class="formLabel-controlCell tableContainer-valueCell"> - <div data-dojo-type="dojo/store/Memory" data-dojo-id="nodeQuorumOverrideStore" - data-dojo-props="data: [{id: '0', name: 'Majority'}]"></div> - <input type="text" id="editVirtualHostNode.quorumOverride" - data-dojo-type="dijit/form/FilteringSelect" - data-dojo-props=" - name: 'quorumOverride', - required: false, - title: 'Select minimum required number of nodes or choose Majority', - promptMessage: 'Modifies the minimum number of nodes required to be present to elect a master or commit transactions.<br/>Majority signifies that a natural majority of nodes must be present.', - store: nodeQuorumOverrideStore, - searchAttr: 'name'" /> - </div> - </div> - - <div class="clear"></div> -</div> diff --git a/qpid/java/bdbstore/src/main/java/resources/virtualhostnode/bdb_ha/show.html b/qpid/java/bdbstore/src/main/java/resources/virtualhostnode/bdb_ha/show.html deleted file mode 100644 index 690440cf7b..0000000000 --- a/qpid/java/bdbstore/src/main/java/resources/virtualhostnode/bdb_ha/show.html +++ /dev/null @@ -1,65 +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. - - - --> -<div> - <div class="clear"> - <div class="formLabel-labelCell">Group name:</div> - <div class="groupName"></div> - </div> - <div class="clear"> - <div class="formLabel-labelCell">Configuration store path:</div> - <div class="storePath"></div> - </div> - <div class="clear"> - <div class="formLabel-labelCell">Role:</div> - <div class="role">N/A</div> - </div> - <div class="clear"> - <div class="formLabel-labelCell">Address:</div> - <div class="address">N/A</div> - </div> - <div class="clear"> - <div class="formLabel-labelCell">Permitted nodes:</div> - <div class="permittedNodes multiLineValue"></div> - </div> - <div class="clear designatedPrimaryContainer"> - <div class="formLabel-labelCell">Allow this node to operate solo:</div> - <div class="designatedPrimary">N/A</div> - </div> - <div class="clear priorityContainer"> - <div class="formLabel-labelCell">Election priority:</div> - <div class="priority">Never</div> - </div> - <div class="clear quorumOverrideContainer"> - <div class="formLabel-labelCell">Required minimum number of nodes:</div> - <div> - <span class="quorumOverride" >N/A</span> - </div> - </div> - <br/> - <div class="clear"></div> - <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Group nodes'" class="membersGridPanel"> - <div class="groupMembers"></div> - <div class="groupMembersToolbar dijitDialogPaneActionBar"> - <button data-dojo-type="dijit.form.Button" class="removeNodeButton" data-dojo-props="iconClass: 'dijitIconDelete'">Remove Node</button> - <button data-dojo-type="dijit.form.Button" class="transferMasterButton" data-dojo-props="iconClass: 'dijitIconConfigure'">Make Node Master</button> - </div> - </div> -</div> diff --git a/qpid/java/bdbstore/src/main/resources/backup-log4j.xml b/qpid/java/bdbstore/src/main/resources/backup-log4j.xml deleted file mode 100644 index 6b0619f0b6..0000000000 --- a/qpid/java/bdbstore/src/main/resources/backup-log4j.xml +++ /dev/null @@ -1,65 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - - - - 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. - - - --> -<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> - -<!-- =============================================================================== --> -<!-- This is a Log4j configuration specially created for the BDB Backup utility, --> -<!-- it outputs logging to the console for specifically designated console loggers --> -<!-- at info level or above only. This avoids spamming the user with any internals --> -<!-- of the Qpid code. --> -<!-- Use a different logging set up to capture debugging output to diagnose errors. --> -<!-- =============================================================================== --> - -<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false"> - - <!-- ====================================================== --> - <!-- Append messages to the console at info level or above. --> - <!-- ====================================================== --> - - <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender"> - <param name="Target" value="System.out"/> - <param name="Threshold" value="info"/> - - <layout class="org.apache.log4j.PatternLayout"> - <!-- The default pattern: Date Priority [Category] Message\n --> - <param name="ConversionPattern" value="%m%n"/> - </layout> - - </appender> - - <!-- ================ --> - <!-- Limit categories --> - <!-- ================ --> - - <category name="org.apache.qpid.server.store.berkeleydb.BDBBackup"> - <priority value="info"/> - </category> - - <!-- ======================= --> - <!-- Setup the Root category --> - <!-- ======================= --> - - <root> - <appender-ref ref="CONSOLE"/> - </root> - -</log4j:configuration> diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/AMQShortStringEncodingTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/AMQShortStringEncodingTest.java deleted file mode 100644 index 67804dc234..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/AMQShortStringEncodingTest.java +++ /dev/null @@ -1,87 +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.TupleInput; -import com.sleepycat.bind.tuple.TupleOutput; -import junit.framework.TestCase; - -import org.apache.qpid.framing.AMQShortString; - -/** - * Tests for {@code AMQShortStringEncoding} including corner cases when string - * is null or over 127 characters in length - */ -public class AMQShortStringEncodingTest extends TestCase -{ - - public void testWriteReadNullValues() - { - // write into tuple output - TupleOutput tupleOutput = new TupleOutput(); - AMQShortStringEncoding.writeShortString(null, tupleOutput); - byte[] data = tupleOutput.getBufferBytes(); - - // read from tuple input - TupleInput tupleInput = new TupleInput(data); - AMQShortString result = AMQShortStringEncoding.readShortString(tupleInput); - assertNull("Expected null but got " + result, result); - } - - public void testWriteReadShortStringWithLengthOver127() - { - AMQShortString value = createString('a', 128); - - // write into tuple output - TupleOutput tupleOutput = new TupleOutput(); - AMQShortStringEncoding.writeShortString(value, tupleOutput); - byte[] data = tupleOutput.getBufferBytes(); - - // read from tuple input - TupleInput tupleInput = new TupleInput(data); - AMQShortString result = AMQShortStringEncoding.readShortString(tupleInput); - assertEquals("Expected " + value + " but got " + result, value, result); - } - - public void testWriteReadShortStringWithLengthLess127() - { - AMQShortString value = new AMQShortString("test"); - - // write into tuple output - TupleOutput tupleOutput = new TupleOutput(); - AMQShortStringEncoding.writeShortString(value, tupleOutput); - byte[] data = tupleOutput.getBufferBytes(); - - // read from tuple input - TupleInput tupleInput = new TupleInput(data); - AMQShortString result = AMQShortStringEncoding.readShortString(tupleInput); - assertEquals("Expected " + value + " but got " + result, value, result); - } - - private AMQShortString createString(char ch, int length) - { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < length; i++) - { - sb.append(ch); - } - return new AMQShortString(sb.toString()); - } - -} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java deleted file mode 100644 index ee990d3211..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java +++ /dev/null @@ -1,795 +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 static org.mockito.Mockito.when; - -import java.io.File; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -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.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -import com.sleepycat.je.Durability; -import com.sleepycat.je.EnvironmentConfig; -import com.sleepycat.je.rep.ReplicatedEnvironment; -import com.sleepycat.je.rep.ReplicationConfig; - -import org.apache.qpid.server.configuration.IllegalConfigurationException; -import org.apache.qpid.server.model.AbstractConfiguredObject; -import org.apache.qpid.server.model.ConfigurationChangeListener; -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.model.RemoteReplicationNode; -import org.apache.qpid.server.model.State; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.store.DurableConfigurationStore; -import org.apache.qpid.server.store.berkeleydb.replication.DatabasePinger; -import org.apache.qpid.server.virtualhost.berkeleydb.BDBHAVirtualHost; -import org.apache.qpid.server.virtualhost.berkeleydb.BDBHAVirtualHostImpl; -import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHARemoteReplicationNode; -import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHARemoteReplicationNodeImpl; -import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNode; -import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNodeTestHelper; -import org.apache.qpid.server.virtualhostnode.berkeleydb.NodeRole; -import org.apache.qpid.test.utils.PortHelper; -import org.apache.qpid.test.utils.QpidTestCase; -import org.apache.qpid.test.utils.TestFileUtils; -import org.apache.qpid.util.FileUtils; - -public class BDBHAVirtualHostNodeTest extends QpidTestCase -{ - private BDBHAVirtualHostNodeTestHelper _helper; - private PortHelper _portHelper = new PortHelper(); - - @Override - protected void setUp() throws Exception - { - super.setUp(); - - _helper = new BDBHAVirtualHostNodeTestHelper(getTestName()); - } - - @Override - protected void tearDown() throws Exception - { - try - { - _helper.tearDown(); - } - finally - { - super.tearDown(); - } - - _portHelper.waitUntilAllocatedPortsAreFree(); - } - - public void testCreateAndActivateVirtualHostNode() throws Exception - { - int node1PortNumber = _portHelper.getNextAvailable(); - String helperAddress = "localhost:" + node1PortNumber; - String groupName = "group"; - String nodeName = "node1"; - - Map<String, Object> attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, node1PortNumber); - String messageStorePath = (String)attributes.get(BDBHAVirtualHostNode.STORE_PATH); - String repStreamTimeout = "2 h"; - Map<String,String> context = (Map<String,String>)attributes.get(BDBHAVirtualHostNode.CONTEXT); - context.put(ReplicationConfig.REP_STREAM_TIMEOUT, repStreamTimeout); - BDBHAVirtualHostNode<?> node = _helper.createHaVHN(attributes); - - node.start(); - _helper.assertNodeRole(node, NodeRole.MASTER, NodeRole.REPLICA); - - assertEquals("Unexpected node state", State.ACTIVE, node.getState()); - - DurableConfigurationStore store = node.getConfigurationStore(); - assertNotNull(store); - - BDBConfigurationStore bdbConfigurationStore = (BDBConfigurationStore) store; - ReplicatedEnvironment environment = (ReplicatedEnvironment) bdbConfigurationStore.getEnvironmentFacade().getEnvironment(); - ReplicationConfig replicationConfig = environment.getRepConfig(); - - assertEquals(nodeName, environment.getNodeName()); - assertEquals(groupName, environment.getGroup().getName()); - assertEquals(helperAddress, replicationConfig.getNodeHostPort()); - assertEquals(helperAddress, replicationConfig.getHelperHosts()); - - assertEquals("SYNC,NO_SYNC,SIMPLE_MAJORITY", environment.getConfig().getDurability().toString()); - assertEquals("Unexpected JE replication stream timeout", repStreamTimeout, replicationConfig.getConfigParam(ReplicationConfig.REP_STREAM_TIMEOUT)); - - _helper.awaitForVirtualhost(node, 30000); - VirtualHost<?, ?, ?> virtualHost = node.getVirtualHost(); - assertNotNull("Virtual host child was not added", virtualHost); - assertEquals("Unexpected virtual host name", groupName, virtualHost.getName()); - assertEquals("Unexpected virtual host store", bdbConfigurationStore.getMessageStore(), virtualHost.getMessageStore()); - assertEquals("Unexpected virtual host state", State.ACTIVE, virtualHost.getState()); - - node.stop(); - assertEquals("Unexpected state returned after stop", State.STOPPED, node.getState()); - assertEquals("Unexpected state", State.STOPPED, node.getState()); - - assertNull("Virtual host is not destroyed", node.getVirtualHost()); - - node.delete(); - assertEquals("Unexpected state returned after delete", State.DELETED, node.getState()); - assertEquals("Unexpected state", State.DELETED, node.getState()); - assertFalse("Store still exists " + messageStorePath, new File(messageStorePath).exists()); - } - - public void testMutableAttributes() throws Exception - { - int node1PortNumber = _portHelper.getNextAvailable(); - String helperAddress = "localhost:" + node1PortNumber; - String groupName = "group"; - String nodeName = "node1"; - - Map<String, Object> attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, node1PortNumber); - BDBHAVirtualHostNode<?> node = _helper.createAndStartHaVHN(attributes); - - BDBConfigurationStore bdbConfigurationStore = (BDBConfigurationStore) node.getConfigurationStore(); - ReplicatedEnvironment environment = (ReplicatedEnvironment) bdbConfigurationStore.getEnvironmentFacade().getEnvironment(); - - assertEquals("Unexpected node priority value before mutation", 1, environment.getRepMutableConfig().getNodePriority()); - assertFalse("Unexpected designated primary value before mutation", environment.getRepMutableConfig().getDesignatedPrimary()); - assertEquals("Unexpected electable group override value before mutation", 0, environment.getRepMutableConfig().getElectableGroupSizeOverride()); - - node.setAttribute(BDBHAVirtualHostNode.PRIORITY, 1, 2); - node.setAttribute(BDBHAVirtualHostNode.DESIGNATED_PRIMARY, false, true); - node.setAttribute(BDBHAVirtualHostNode.QUORUM_OVERRIDE, 0, 1); - - assertEquals("Unexpected node priority value after mutation", 2, environment.getRepMutableConfig().getNodePriority()); - assertTrue("Unexpected designated primary value after mutation", environment.getRepMutableConfig().getDesignatedPrimary()); - assertEquals("Unexpected electable group override value after mutation", 1, environment.getRepMutableConfig().getElectableGroupSizeOverride()); - - assertNotNull("Join time should be set", node.getJoinTime()); - assertNotNull("Last known replication transaction id should be set", node.getLastKnownReplicationTransactionId()); - } - - public void testTransferMasterToSelf() throws Exception - { - int node1PortNumber = _portHelper.getNextAvailable(); - int node2PortNumber = _portHelper.getNextAvailable(); - int node3PortNumber = _portHelper.getNextAvailable(); - - String helperAddress = "localhost:" + node1PortNumber; - String groupName = "group"; - String nodeName = "node1"; - - Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, node1PortNumber, node2PortNumber, node3PortNumber); - _helper.createAndStartHaVHN(node1Attributes); - - Map<String, Object> node2Attributes = _helper.createNodeAttributes("node2", groupName, "localhost:" + node2PortNumber, helperAddress, nodeName); - _helper.createAndStartHaVHN(node2Attributes); - - Map<String, Object> node3Attributes = _helper.createNodeAttributes("node3", groupName, "localhost:" + node3PortNumber, helperAddress, nodeName); - _helper.createAndStartHaVHN(node3Attributes); - - BDBHAVirtualHostNode<?> replica = _helper.awaitAndFindNodeInRole(NodeRole.REPLICA); - - replica.setAttribute(BDBHAVirtualHostNode.ROLE, replica.getRole(), NodeRole.MASTER); - - _helper.assertNodeRole(replica, NodeRole.MASTER); - } - - public void testTransferMasterToRemoteReplica() throws Exception - { - int node1PortNumber = _portHelper.getNextAvailable(); - int node2PortNumber = _portHelper.getNextAvailable(); - int node3PortNumber = _portHelper.getNextAvailable(); - - String helperAddress = "localhost:" + node1PortNumber; - String groupName = "group"; - String nodeName = "node1"; - - Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, - helperAddress, nodeName, node1PortNumber, node2PortNumber, node3PortNumber); - BDBHAVirtualHostNode<?> node1 = _helper.createAndStartHaVHN(node1Attributes); - - final AtomicReference<RemoteReplicationNode<?>> lastSeenReplica = new AtomicReference<>(); - final CountDownLatch remoteNodeLatch = new CountDownLatch(2); - node1.addChangeListener(new NoopConfigurationChangeListener() - { - @Override - public void childAdded(ConfiguredObject<?> object, ConfiguredObject<?> child) - { - if (child instanceof RemoteReplicationNode) - { - remoteNodeLatch.countDown(); - lastSeenReplica.set((RemoteReplicationNode<?>)child); - } - } - }); - - Map<String, Object> node2Attributes = _helper.createNodeAttributes("node2", groupName, "localhost:" + node2PortNumber, helperAddress, nodeName); - BDBHAVirtualHostNode<?> node2 = _helper.createAndStartHaVHN(node2Attributes); - - Map<String, Object> node3Attributes = _helper.createNodeAttributes("node3", groupName, "localhost:" + node3PortNumber, helperAddress, nodeName); - BDBHAVirtualHostNode<?> node3 = _helper.createAndStartHaVHN(node3Attributes); - - assertTrue("Replication nodes have not been seen during 5s", remoteNodeLatch.await(5, TimeUnit.SECONDS)); - - BDBHARemoteReplicationNodeImpl replicaRemoteNode = (BDBHARemoteReplicationNodeImpl)lastSeenReplica.get(); - _helper.awaitForAttributeChange(replicaRemoteNode, BDBHARemoteReplicationNodeImpl.ROLE, NodeRole.REPLICA); - - replicaRemoteNode.setAttributes(Collections.<String,Object>singletonMap(BDBHARemoteReplicationNode.ROLE, NodeRole.MASTER)); - - BDBHAVirtualHostNode<?> replica = replicaRemoteNode.getName().equals(node2.getName())? node2 : node3; - _helper.assertNodeRole(replica, NodeRole.MASTER); - } - - public void testMutatingRoleWhenNotReplica_IsDisallowed() throws Exception - { - int nodePortNumber = _portHelper.getNextAvailable(); - String helperAddress = "localhost:" + nodePortNumber; - String groupName = "group"; - String nodeName = "node1"; - - Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, nodePortNumber); - BDBHAVirtualHostNode<?> node = _helper.createAndStartHaVHN(node1Attributes); - _helper.assertNodeRole(node, NodeRole.MASTER); - - try - { - node.setAttributes(Collections.<String,Object>singletonMap(BDBHAVirtualHostNode.ROLE, NodeRole.REPLICA)); - fail("Role mutation should fail"); - } - catch(IllegalStateException e) - { - // PASS - } - } - - - public void testRemoveReplicaNode() throws Exception - { - int node1PortNumber = _portHelper.getNextAvailable(); - int node2PortNumber = _portHelper.getNextAvailable(); - int node3PortNumber = _portHelper.getNextAvailable(); - - String helperAddress = "localhost:" + node1PortNumber; - String groupName = "group"; - String nodeName = "node1"; - - assertTrue(_portHelper.isPortAvailable(node1PortNumber)); - - Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, node1PortNumber, node2PortNumber, node3PortNumber); - _helper.createAndStartHaVHN(node1Attributes); - - assertTrue(_portHelper.isPortAvailable(node2PortNumber)); - - Map<String, Object> node2Attributes = _helper.createNodeAttributes("node2", groupName, "localhost:" + node2PortNumber, helperAddress, nodeName); - _helper.createAndStartHaVHN(node2Attributes); - - assertTrue(_portHelper.isPortAvailable(node3PortNumber)); - - Map<String, Object> node3Attributes = _helper.createNodeAttributes("node3", groupName, "localhost:" + node3PortNumber, helperAddress, nodeName); - _helper.createAndStartHaVHN(node3Attributes); - - - BDBHAVirtualHostNode<?> master = _helper.awaitAndFindNodeInRole(NodeRole.MASTER); - _helper.awaitRemoteNodes(master, 2); - - BDBHAVirtualHostNode<?> replica = _helper.awaitAndFindNodeInRole(NodeRole.REPLICA); - _helper.awaitRemoteNodes(replica, 2); - - assertNotNull("Remote node " + replica.getName() + " is not found", _helper.findRemoteNode(master, replica.getName())); - replica.delete(); - - _helper.awaitRemoteNodes(master, 1); - - assertNull("Remote node " + replica.getName() + " is not found", _helper.findRemoteNode(master, replica.getName())); - } - - public void testSetSynchronizationPolicyAttributesOnVirtualHost() throws Exception - { - int node1PortNumber = _portHelper.getNextAvailable(); - String helperAddress = "localhost:" + node1PortNumber; - String groupName = "group"; - String nodeName = "node1"; - - Map<String, Object> nodeAttributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, node1PortNumber); - BDBHAVirtualHostNode<?> node = _helper.createHaVHN(nodeAttributes); - - node.start(); - _helper.assertNodeRole(node, NodeRole.MASTER, NodeRole.REPLICA); - assertEquals("Unexpected node state", State.ACTIVE, node.getState()); - - _helper.awaitForVirtualhost(node,30000); - BDBHAVirtualHostImpl virtualHost = (BDBHAVirtualHostImpl)node.getVirtualHost(); - assertNotNull("Virtual host is not created", virtualHost); - - _helper.awaitForAttributeChange(virtualHost, BDBHAVirtualHostImpl.COALESCING_SYNC, true); - - assertEquals("Unexpected local transaction synchronization policy", "SYNC", virtualHost.getLocalTransactionSynchronizationPolicy()); - assertEquals("Unexpected remote transaction synchronization policy", "NO_SYNC", virtualHost.getRemoteTransactionSynchronizationPolicy()); - assertTrue("CoalescingSync is not ON", virtualHost.isCoalescingSync()); - - Map<String, Object> virtualHostAttributes = new HashMap<String,Object>(); - virtualHostAttributes.put(BDBHAVirtualHost.LOCAL_TRANSACTION_SYNCHRONIZATION_POLICY, "WRITE_NO_SYNC"); - virtualHostAttributes.put(BDBHAVirtualHost.REMOTE_TRANSACTION_SYNCHRONIZATION_POLICY, "SYNC"); - virtualHost.setAttributes(virtualHostAttributes); - - virtualHost.stop(); - virtualHost.start(); - - assertEquals("Unexpected local transaction synchronization policy", "WRITE_NO_SYNC", virtualHost.getLocalTransactionSynchronizationPolicy()); - assertEquals("Unexpected remote transaction synchronization policy", "SYNC", virtualHost.getRemoteTransactionSynchronizationPolicy()); - assertFalse("CoalescingSync is not OFF", virtualHost.isCoalescingSync()); - try - { - virtualHost.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHost.LOCAL_TRANSACTION_SYNCHRONIZATION_POLICY, "INVALID")); - fail("Invalid synchronization policy is set"); - } - catch(IllegalArgumentException e) - { - //pass - } - - try - { - virtualHost.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHost.REMOTE_TRANSACTION_SYNCHRONIZATION_POLICY, "INVALID")); - fail("Invalid synchronization policy is set"); - } - catch(IllegalArgumentException e) - { - //pass - } - - } - - public void testNotPermittedNodeIsNotAllowedToConnect() throws Exception - { - int node1PortNumber = _portHelper.getNextAvailable(); - int node2PortNumber = _portHelper.getNextAvailable(); - int node3PortNumber = _portHelper.getNextAvailable(); - - String helperAddress = "localhost:" + node1PortNumber; - String groupName = "group"; - String nodeName = "node1"; - - Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, node1PortNumber, node2PortNumber); - BDBHAVirtualHostNode<?> node1 = _helper.createAndStartHaVHN(node1Attributes); - - Map<String, Object> node2Attributes = _helper.createNodeAttributes("node2", groupName, "localhost:" + node2PortNumber, helperAddress, nodeName); - BDBHAVirtualHostNode<?> node2 = _helper.createAndStartHaVHN(node2Attributes); - - Map<String, Object> node3Attributes = _helper.createNodeAttributes("node3", groupName, "localhost:" + node3PortNumber, helperAddress, nodeName); - try - { - _helper.createHaVHN(node3Attributes); - fail("The VHN should not be permitted to join the group"); - } - catch(IllegalConfigurationException e) - { - assertEquals("Unexpected exception message", String.format("Node from '%s' is not permitted!", "localhost:" + node3PortNumber), e.getMessage()); - } - } - - public void testCurrentNodeCannotBeRemovedFromPermittedNodeList() throws Exception - { - int node1PortNumber = _portHelper.getNextAvailable(); - int node2PortNumber = _portHelper.getNextAvailable(); - int node3PortNumber = _portHelper.getNextAvailable(); - - String node1Address = "localhost:" + node1PortNumber; - String node2Address = "localhost:" + node2PortNumber; - String node3Address = "localhost:" + node3PortNumber; - - String groupName = "group"; - String node1Name = "node1"; - - Map<String, Object> node1Attributes = _helper.createNodeAttributes(node1Name, groupName, node1Address, node1Address, node1Name, node1PortNumber, node2PortNumber, node3PortNumber); - BDBHAVirtualHostNode<?> node1 = _helper.createAndStartHaVHN(node1Attributes); - - Map<String, Object> node2Attributes = _helper.createNodeAttributes("node2", groupName, node2Address, node1Address, node1Name); - BDBHAVirtualHostNode<?> node2 = _helper.createAndStartHaVHN(node2Attributes); - - Map<String, Object> node3Attributes = _helper.createNodeAttributes("node3", groupName, node3Address, node1Address, node1Name); - BDBHAVirtualHostNode<?> node3 = _helper.createAndStartHaVHN(node3Attributes); - - _helper.awaitRemoteNodes(node1, 2); - - // Create new "proposed" permitted nodes list with a current node missing - List<String> amendedPermittedNodes = new ArrayList<String>(); - amendedPermittedNodes.add(node1Address); - amendedPermittedNodes.add(node2Address); - - // Try to update the permitted nodes attributes using the new list - try - { - node1.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.PERMITTED_NODES, amendedPermittedNodes)); - fail("Operation to remove current group node from permitted nodes should have failed"); - } - catch(IllegalArgumentException e) - { - assertEquals("Unexpected exception message", String.format("The current group node '%s' cannot be removed from '%s' as its already a group member", node3Address, BDBHAVirtualHostNode.PERMITTED_NODES), e.getMessage()); - } - } - - public void testPermittedNodesAttributeModificationConditions() throws Exception - { - int node1PortNumber = _portHelper.getNextAvailable(); - int node2PortNumber = _portHelper.getNextAvailable(); - int node3PortNumber = _portHelper.getNextAvailable(); - int node4PortNumber = _portHelper.getNextAvailable(); - int node5PortNumber = _portHelper.getNextAvailable(); - - String node1Address = "localhost:" + node1PortNumber; - String node2Address = "localhost:" + node2PortNumber; - String node3Address = "localhost:" + node3PortNumber; - String node4Address = "localhost:" + node4PortNumber; - String node5Address = "localhost:" + node5PortNumber; - - String groupName = "group"; - String node1Name = "node1"; - - Map<String, Object> node1Attributes = _helper.createNodeAttributes(node1Name, groupName, node1Address, node1Address, node1Name, node1PortNumber, node2PortNumber, node3PortNumber); - BDBHAVirtualHostNode<?> node1 = _helper.createAndStartHaVHN(node1Attributes); - - Map<String, Object> node2Attributes = _helper.createNodeAttributes("node2", groupName, node2Address, node1Address, node1Name); - BDBHAVirtualHostNode<?> node2 = _helper.createAndStartHaVHN(node2Attributes); - - Map<String, Object> node3Attributes = _helper.createNodeAttributes("node3", groupName, node3Address, node1Address, node1Name); - BDBHAVirtualHostNode<?> node3 = _helper.createAndStartHaVHN(node3Attributes); - - _helper.awaitRemoteNodes(node1, 2); - - // Create new "proposed" permitted nodes list for update - List<String> amendedPermittedNodes = new ArrayList<String>(); - amendedPermittedNodes.add(node1Address); - amendedPermittedNodes.add(node2Address); - amendedPermittedNodes.add(node3Address); - amendedPermittedNodes.add(node4Address); - - // Try to update the permitted nodes attributes using the new list on REPLICA - should fail - BDBHAVirtualHostNode<?> nonMasterNode = _helper.findNodeInRole(NodeRole.REPLICA); - try - { - nonMasterNode.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.PERMITTED_NODES, amendedPermittedNodes)); - fail("Operation to update permitted nodes should have failed from non MASTER node"); - } - catch(IllegalArgumentException e) - { - assertEquals("Unexpected exception message", String.format("Attribute '%s' can only be set on '%s' node or node in '%s' or '%s' state", BDBHAVirtualHostNode.PERMITTED_NODES, NodeRole.MASTER, State.STOPPED, State.ERRORED), e.getMessage()); - } - - // Try to update the permitted nodes attributes using the new list on MASTER - should succeed - BDBHAVirtualHostNode<?> masterNode = _helper.findNodeInRole(NodeRole.MASTER); - masterNode.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.PERMITTED_NODES, amendedPermittedNodes)); - - // Try to update the permitted nodes attributes using the new list on a STOPPED node - should succeed - nonMasterNode.stop(); - amendedPermittedNodes.add(node5Address); - nonMasterNode.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.PERMITTED_NODES, amendedPermittedNodes)); - } - - public void testIntruderProtection() throws Exception - { - int nodePortNumber = _portHelper.getNextAvailable(); - int intruderPortNumber = _portHelper.getNextAvailable(); - - String helperAddress = "localhost:" + nodePortNumber; - String groupName = "group"; - String nodeName = "node"; - - Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, nodePortNumber, intruderPortNumber); - BDBHAVirtualHostNode<?> node = _helper.createAndStartHaVHN(node1Attributes); - - Map<String, Object> intruderAttributes = _helper.createNodeAttributes("intruder", groupName, "localhost:" + intruderPortNumber, helperAddress, nodeName); - intruderAttributes.put(BDBHAVirtualHostNode.PRIORITY, 0); - BDBHAVirtualHostNode<?> intruder = _helper.createAndStartHaVHN(intruderAttributes); - - final CountDownLatch stopLatch = new CountDownLatch(1); - ConfigurationChangeListener listener = new NoopConfigurationChangeListener() - { - @Override - public void stateChanged(ConfiguredObject<?> object, State oldState, State newState) - { - if (newState == State.ERRORED) - { - stopLatch.countDown(); - } - } - }; - node.addChangeListener(listener); - - List<String> permittedNodes = new ArrayList<String>(); - permittedNodes.add(helperAddress); - node.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.PERMITTED_NODES, permittedNodes)); - - assertTrue("Intruder protection was not triggered during expected timeout", stopLatch.await(10, TimeUnit.SECONDS)); - - // Try top re start the ERRORED node and ensure exception is thrown - try - { - node.start(); - fail("Restart of node should have thrown exception"); - } - catch (IllegalStateException ise) - { - assertEquals("Unexpected exception when restarting node post intruder detection", "Intruder node detected: " + "localhost:" + intruderPortNumber, ise.getMessage()); - } - _helper.awaitForAttributeChange(node, AbstractConfiguredObject.STATE, State.ERRORED); - } - - public void testIntruderProtectionInManagementMode() throws Exception - { - int nodePortNumber = _portHelper.getNextAvailable(); - int intruderPortNumber = _portHelper.getNextAvailable(); - - String helperAddress = "localhost:" + nodePortNumber; - String groupName = "group"; - String nodeName = "node"; - - Map<String, Object> nodeAttributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, nodePortNumber, intruderPortNumber); - BDBHAVirtualHostNode<?> node = _helper.createAndStartHaVHN(nodeAttributes); - - Map<String, Object> intruderAttributes = _helper.createNodeAttributes("intruder", groupName, "localhost:" + intruderPortNumber, helperAddress, nodeName); - intruderAttributes.put(BDBHAVirtualHostNode.PRIORITY, 0); - BDBHAVirtualHostNode<?> intruder = _helper.createAndStartHaVHN(intruderAttributes); - - final CountDownLatch stopLatch = new CountDownLatch(1); - ConfigurationChangeListener listener = new NoopConfigurationChangeListener() - { - @Override - public void stateChanged(ConfiguredObject<?> object, State oldState, State newState) - { - if (newState == State.ERRORED) - { - stopLatch.countDown(); - } - } - }; - node.addChangeListener(listener); - - List<String> permittedNodes = new ArrayList<String>(); - permittedNodes.add(helperAddress); - node.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.PERMITTED_NODES, permittedNodes)); - - assertTrue("Intruder protection was not triggered during expected timeout", stopLatch.await(10, TimeUnit.SECONDS)); - - // test that if management mode is enabled then the node can start without exception - when(_helper.getBroker().isManagementMode()).thenReturn(true); - node.start(); - - _helper.awaitForAttributeChange(node, AbstractConfiguredObject.STATE, State.ERRORED); - } - - public void testPermittedNodesChangedOnReplicaNodeOnlyOnceAfterBeingChangedOnMaster() throws Exception - { - int node1PortNumber = _portHelper.getNextAvailable(); - int node2PortNumber = _portHelper.getNextAvailable(); - - String helperAddress = "localhost:" + node1PortNumber; - String groupName = "group"; - String nodeName = "node1"; - - Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, node1PortNumber, node2PortNumber); - BDBHAVirtualHostNode<?> node1 = _helper.createAndStartHaVHN(node1Attributes); - - Map<String, Object> node2Attributes = _helper.createNodeAttributes("node2", groupName, "localhost:" + node2PortNumber, helperAddress, nodeName); - node2Attributes.put(BDBHAVirtualHostNode.PRIORITY, 0); - BDBHAVirtualHostNode<?> node2 = _helper.createAndStartHaVHN(node2Attributes); - assertEquals("Unexpected role", NodeRole.REPLICA, node2.getRole()); - _helper.awaitRemoteNodes(node2, 1); - - BDBHARemoteReplicationNode<?> remote = _helper.findRemoteNode(node2, node1.getName()); - - final AtomicInteger permittedNodesChangeCounter = new AtomicInteger(); - final CountDownLatch _permittedNodesLatch = new CountDownLatch(1); - node2.addChangeListener(new NoopConfigurationChangeListener() - { - @Override - public void attributeSet(ConfiguredObject<?> object, String attributeName, Object oldAttributeValue, Object newAttributeValue) - { - if (attributeName.equals(BDBHAVirtualHostNode.PERMITTED_NODES)) - { - permittedNodesChangeCounter.incrementAndGet(); - _permittedNodesLatch.countDown(); - } - } - }); - List<String> permittedNodes = new ArrayList<>(node1.getPermittedNodes()); - permittedNodes.add("localhost:5000"); - node1.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.PERMITTED_NODES, permittedNodes)); - - assertTrue("Permitted nodes were not changed on Replica", _permittedNodesLatch.await(10, TimeUnit.SECONDS)); - assertEquals("Not the same permitted nodes", new HashSet<>(node1.getPermittedNodes()), new HashSet<>(node2.getPermittedNodes())); - assertEquals("Unexpected counter of changes permitted nodes", 1, permittedNodesChangeCounter.get()); - - // change the order of permitted nodes - Collections.swap(permittedNodes, 0, 2); - node1.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.PERMITTED_NODES, permittedNodes)); - - // make sure that node2 onNodeState was invoked by performing transaction on master and making sure that it was replicated - performTransactionAndAwaitForRemoteNodeToGetAware(node1, remote); - - // perform transaction second time because permitted nodes are changed after last transaction id - performTransactionAndAwaitForRemoteNodeToGetAware(node1, remote); - assertEquals("Unexpected counter of changes permitted nodes", 1, permittedNodesChangeCounter.get()); - } - - private void performTransactionAndAwaitForRemoteNodeToGetAware(BDBHAVirtualHostNode<?> node1, BDBHARemoteReplicationNode<?> remote) throws InterruptedException - { - new DatabasePinger().pingDb(((BDBConfigurationStore)node1.getConfigurationStore()).getEnvironmentFacade()); - - int waitCounter = 100; - while ( remote.getLastKnownReplicationTransactionId() != node1.getLastKnownReplicationTransactionId() && (waitCounter--) != 0) - { - Thread.sleep(100l); - } - assertEquals("Last transaction was not replicated", new Long(remote.getLastKnownReplicationTransactionId()), node1.getLastKnownReplicationTransactionId() ); - } - - public void testIntruderConnected() throws Exception - { - int node1PortNumber = _portHelper.getNextAvailable(); - int node2PortNumber = _portHelper.getNextAvailable(); - - String helperAddress = "localhost:" + node1PortNumber; - String groupName = "group"; - String nodeName = "node1"; - - Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, node1PortNumber); - BDBHAVirtualHostNode<?> node1 = _helper.createAndStartHaVHN(node1Attributes); - - final CountDownLatch stopLatch = new CountDownLatch(1); - ConfigurationChangeListener listener = new NoopConfigurationChangeListener() - { - @Override - public void stateChanged(ConfiguredObject<?> object, State oldState, State newState) - { - if (newState == State.ERRORED) - { - stopLatch.countDown(); - } - } - }; - node1.addChangeListener(listener); - - String node2Name = "node2"; - File environmentPathFile = new File(_helper.getMessageStorePath() + File.separator + node2Name); - environmentPathFile.mkdirs(); - - ReplicationConfig replicationConfig = new ReplicationConfig(groupName, node2Name, "localhost:" + node2PortNumber ); - replicationConfig.setHelperHosts(helperAddress); - EnvironmentConfig envConfig = new EnvironmentConfig(); - envConfig.setAllowCreate(true); - envConfig.setTransactional(true); - envConfig.setDurability(Durability.parse((String) node1Attributes.get(BDBHAVirtualHostNode.DURABILITY))); - - ReplicatedEnvironment intruder = null; - String originalThreadName = Thread.currentThread().getName(); - try - { - intruder = new ReplicatedEnvironment(environmentPathFile, replicationConfig, envConfig); - } - finally - { - try - { - if (intruder != null) - { - intruder.close(); - } - } - finally - { - Thread.currentThread().setName(originalThreadName); - } - } - - assertTrue("Intruder protection was not triggered during expected timeout", stopLatch.await(20, TimeUnit.SECONDS)); - } - - public void testValidateOnCreateForNonExistingHelperNode() throws Exception - { - int node1PortNumber = findFreePort(); - int node2PortNumber = getNextAvailable(node1PortNumber + 1); - - - Map<String, Object> attributes = _helper.createNodeAttributes("node1", "group", "localhost:" + node1PortNumber, - "localhost:" + node2PortNumber, "node2", node1PortNumber, node1PortNumber, node2PortNumber); - try - { - _helper.createAndStartHaVHN(attributes); - fail("Node creation should fail because of invalid helper address"); - } - catch(IllegalConfigurationException e) - { - assertEquals("Unexpected exception on connection to non-existing helper address", - String.format("Cannot connect to existing node '%s' at '%s'", "node2", "localhost:" + node2PortNumber), e.getMessage()); - } - } - - public void testValidateOnCreateForAlreadyBoundAddress() throws Exception - { - int node1PortNumber = findFreePort(); - - ServerSocket serverSocket = null; - try - { - serverSocket = new ServerSocket(); - serverSocket.setReuseAddress(true); - serverSocket.bind(new InetSocketAddress("localhost", node1PortNumber)); - - - Map<String, Object> attributes = _helper.createNodeAttributes("node1", "group", "localhost:" + node1PortNumber, - "localhost:" + node1PortNumber, "node2", node1PortNumber, node1PortNumber); - try - { - _helper.createAndStartHaVHN(attributes); - fail("Node creation should fail because of invalid address"); - } - catch(IllegalConfigurationException e) - { - assertEquals("Unexpected exception on attempt to create node with already bound address", - String.format("Cannot bind to address '%s'. Address is already in use.", "localhost:" + node1PortNumber), e.getMessage()); - } - } - finally - { - if (serverSocket != null) - { - serverSocket.close(); - } - } - } - - public void testValidateOnCreateForInvalidStorePath() throws Exception - { - int node1PortNumber = findFreePort(); - - File storeBaseFolder = TestFileUtils.createTestDirectory(); - File file = new File(storeBaseFolder, getTestName()); - file.createNewFile(); - File storePath = new File(file, "test"); - try - { - Map<String, Object> attributes = _helper.createNodeAttributes("node1", "group", "localhost:" + node1PortNumber, - "localhost:" + node1PortNumber, "node2", node1PortNumber, node1PortNumber); - attributes.put(BDBHAVirtualHostNode.STORE_PATH, storePath.getAbsoluteFile()); - try - { - _helper.createAndStartHaVHN(attributes); - fail("Node creation should fail because of invalid store path"); - } - catch (IllegalConfigurationException e) - { - assertEquals("Unexpected exception on attempt to create environment in invalid location", - String.format("Store path '%s' is not a folder", storePath.getAbsoluteFile()), e.getMessage()); - } - } - finally - { - FileUtils.delete(storeBaseFolder, true); - } - } -} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreConfigurationTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreConfigurationTest.java deleted file mode 100644 index a58b1e7c2e..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreConfigurationTest.java +++ /dev/null @@ -1,48 +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 static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import org.apache.qpid.server.model.ConfiguredObjectFactory; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.model.VirtualHostNode; -import org.apache.qpid.server.store.AbstractDurableConfigurationStoreTestCase; -import org.apache.qpid.server.store.DurableConfigurationStore; -import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBVirtualHostNode; - -public class BDBMessageStoreConfigurationTest extends AbstractDurableConfigurationStoreTestCase -{ - @Override - protected VirtualHostNode createVirtualHostNode(String storeLocation, ConfiguredObjectFactory factory) - { - final BDBVirtualHostNode parent = mock(BDBVirtualHostNode.class); - when(parent.getStorePath()).thenReturn(storeLocation); - return parent; - } - - @Override - protected DurableConfigurationStore createConfigStore() throws Exception - { - return new BDBConfigurationStore(VirtualHost.class); - } -} 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 deleted file mode 100644 index ee0edb5e59..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreQuotaEventsTest.java +++ /dev/null @@ -1,82 +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 static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.util.Collections; -import java.util.Map; - -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.MessageStoreQuotaEventsTestBase; -import org.apache.qpid.server.virtualhost.berkeleydb.BDBVirtualHost; - -public class BDBMessageStoreQuotaEventsTest extends MessageStoreQuotaEventsTestBase -{ - /* - * Notes on calculation of quota limits. - * - * 150 32kb messages is approximately 4.8MB which is greater than - * OVERFULL_SIZE. - * - * We deliberately use settings that force BDB to use multiple log files, so - * that when one or more of them are subsequently cleaned (following message - * consumption) the actual size on disk is reduced. - */ - - private static final String MAX_BDB_LOG_SIZE = "1000000"; // ~1MB - - private static final int NUMBER_OF_MESSAGES_TO_OVERFILL_STORE = 150; - - private static final long OVERFULL_SIZE = 4000000; // ~4MB - private static final long UNDERFULL_SIZE = 3500000; // ~3.5MB - - @Override - protected int getNumberOfMessagesToFillStore() - { - return NUMBER_OF_MESSAGES_TO_OVERFILL_STORE; - } - - @Override - protected VirtualHost createVirtualHost(String storeLocation) - { - final BDBVirtualHost parent = mock(BDBVirtualHost.class); - Map<String, String> contextMap = Collections.singletonMap("je.log.fileMax", MAX_BDB_LOG_SIZE); - when(parent.getContext()).thenReturn(contextMap); - when(parent.getContextKeys(false)).thenReturn(contextMap.keySet()); - when(parent.getContextValue(eq(String.class),eq("je.log.fileMax"))).thenReturn(MAX_BDB_LOG_SIZE); - when(parent.getStorePath()).thenReturn(storeLocation); - when(parent.getStoreOverfullSize()).thenReturn(OVERFULL_SIZE); - when(parent.getStoreUnderfullSize()).thenReturn(UNDERFULL_SIZE); - return parent; - } - - - @Override - protected MessageStore createStore() throws Exception - { - MessageStore store = new BDBMessageStore(); - return store; - } -} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java deleted file mode 100644 index 3f8c1a7a99..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java +++ /dev/null @@ -1,415 +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 static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.io.File; -import java.nio.ByteBuffer; -import java.util.Arrays; - -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.MessagePublishInfo; -import org.apache.qpid.server.model.VirtualHost; -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.MessageHandle; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.MessageStoreTestCase; -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.virtualhost.berkeleydb.BDBVirtualHost; -import org.apache.qpid.transport.DeliveryProperties; -import org.apache.qpid.transport.Header; -import org.apache.qpid.transport.MessageAcceptMode; -import org.apache.qpid.transport.MessageAcquireMode; -import org.apache.qpid.transport.MessageDeliveryMode; -import org.apache.qpid.transport.MessageDeliveryPriority; -import org.apache.qpid.transport.MessageProperties; -import org.apache.qpid.transport.MessageTransfer; -import org.apache.qpid.util.FileUtils; - -/** - * Subclass of MessageStoreTestCase which runs the standard tests from the superclass against - * the BDB Store as well as additional tests specific to the BDB store-implementation. - */ -public class BDBMessageStoreTest extends MessageStoreTestCase -{ - private static byte[] CONTENT_BYTES = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - - private String _storeLocation; - - @Override - protected void tearDown() throws Exception - { - try - { - super.tearDown(); - } - finally - { - deleteStoreIfExists(); - } - } - - /** - * Tests that message metadata and content are successfully read back from a - * store after it has been reloaded. Both 0-8 and 0-10 metadata is used to - * verify their ability to co-exist within the store and be successful retrieved. - */ - public void testBDBMessagePersistence() throws Exception - { - MessageStore bdbStore = getStore(); - - // Create content ByteBuffers. - // Split the content into 2 chunks for the 0-8 message, as per broker behaviour. - // Use a single chunk for the 0-10 message as per broker behaviour. - String bodyText = "jfhdjsflsdhfjdshfjdslhfjdslhfsjlhfsjkhfdsjkhfdsjkfhdslkjf"; - - ByteBuffer firstContentBytes_0_8 = ByteBuffer.wrap(bodyText.substring(0, 10).getBytes()); - ByteBuffer secondContentBytes_0_8 = ByteBuffer.wrap(bodyText.substring(10).getBytes()); - - ByteBuffer completeContentBody_0_10 = ByteBuffer.wrap(bodyText.getBytes()); - int bodySize = completeContentBody_0_10.limit(); - - /* - * Create and insert a 0-8 message (metadata and multi-chunk content) - */ - MessagePublishInfo pubInfoBody_0_8 = createPublishInfoBody_0_8(); - BasicContentHeaderProperties props_0_8 = createContentHeaderProperties_0_8(); - - ContentHeaderBody chb_0_8 = createContentHeaderBody_0_8(props_0_8, bodySize); - - MessageMetaData messageMetaData_0_8 = new MessageMetaData(pubInfoBody_0_8, chb_0_8); - MessageHandle<MessageMetaData> messageHandle_0_8 = bdbStore.addMessage(messageMetaData_0_8); - - long origArrivalTime_0_8 = messageMetaData_0_8.getArrivalTime(); - - messageHandle_0_8.addContent(firstContentBytes_0_8); - messageHandle_0_8.addContent(secondContentBytes_0_8); - final StoredMessage<MessageMetaData> storedMessage_0_8 = messageHandle_0_8.allContentAdded(); - long messageid_0_8 = storedMessage_0_8.getMessageNumber(); - ((AbstractBDBMessageStore.StoredBDBMessage)messageHandle_0_8).flushToStore(); - - /* - * Create and insert a 0-10 message (metadata and content) - */ - MessageProperties msgProps_0_10 = createMessageProperties_0_10(bodySize); - DeliveryProperties delProps_0_10 = createDeliveryProperties_0_10(); - Header header_0_10 = new Header(delProps_0_10, msgProps_0_10); - - MessageTransfer xfr_0_10 = new MessageTransfer("destination", MessageAcceptMode.EXPLICIT, - MessageAcquireMode.PRE_ACQUIRED, header_0_10, completeContentBody_0_10); - - MessageMetaData_0_10 messageMetaData_0_10 = new MessageMetaData_0_10(xfr_0_10); - MessageHandle<MessageMetaData_0_10> messageHandle_0_10 = bdbStore.addMessage(messageMetaData_0_10); - - long origArrivalTime_0_10 = messageMetaData_0_10.getArrivalTime(); - - messageHandle_0_10.addContent(completeContentBody_0_10); - final StoredMessage<MessageMetaData_0_10> storedMessage_0_10 = messageHandle_0_10.allContentAdded(); - long messageid_0_10 = storedMessage_0_10.getMessageNumber(); - ((AbstractBDBMessageStore.StoredBDBMessage)messageHandle_0_10).flushToStore(); - - /* - * reload the store only (read-only) - */ - reopenStore(); - - /* - * Read back and validate the 0-8 message metadata and content - */ - BDBMessageStore reopenedBdbStore = (BDBMessageStore) getStore(); - StorableMessageMetaData storeableMMD_0_8 = reopenedBdbStore.getMessageMetaData(messageid_0_8); - - assertEquals("Unexpected message type", MessageMetaDataType_0_8.TYPE, storeableMMD_0_8.getType().ordinal()); - assertTrue("Unexpected instance type", storeableMMD_0_8 instanceof MessageMetaData); - MessageMetaData returnedMMD_0_8 = (MessageMetaData) storeableMMD_0_8; - - assertEquals("Message arrival time has changed", origArrivalTime_0_8, returnedMMD_0_8.getArrivalTime()); - - MessagePublishInfo returnedPubBody_0_8 = returnedMMD_0_8.getMessagePublishInfo(); - assertEquals("Message exchange has changed", pubInfoBody_0_8.getExchange(), returnedPubBody_0_8.getExchange()); - assertEquals("Immediate flag has changed", pubInfoBody_0_8.isImmediate(), returnedPubBody_0_8.isImmediate()); - assertEquals("Mandatory flag has changed", pubInfoBody_0_8.isMandatory(), returnedPubBody_0_8.isMandatory()); - assertEquals("Routing key has changed", pubInfoBody_0_8.getRoutingKey(), returnedPubBody_0_8.getRoutingKey()); - - ContentHeaderBody returnedHeaderBody_0_8 = returnedMMD_0_8.getContentHeaderBody(); - assertEquals("ContentHeader ClassID has changed", chb_0_8.getClassId(), returnedHeaderBody_0_8.getClassId()); - assertEquals("ContentHeader weight has changed", chb_0_8.getWeight(), returnedHeaderBody_0_8.getWeight()); - assertEquals("ContentHeader bodySize has changed", chb_0_8.getBodySize(), returnedHeaderBody_0_8.getBodySize()); - - BasicContentHeaderProperties returnedProperties_0_8 = returnedHeaderBody_0_8.getProperties(); - assertEquals("Property ContentType has changed", props_0_8.getContentTypeAsString(), returnedProperties_0_8.getContentTypeAsString()); - assertEquals("Property MessageID has changed", props_0_8.getMessageIdAsString(), returnedProperties_0_8.getMessageIdAsString()); - - ByteBuffer recoveredContent_0_8 = ByteBuffer.allocate((int) chb_0_8.getBodySize()) ; - long recoveredCount_0_8 = reopenedBdbStore.getContent(messageid_0_8, 0, recoveredContent_0_8); - assertEquals("Incorrect amount of payload data recovered", chb_0_8.getBodySize(), recoveredCount_0_8); - String returnedPayloadString_0_8 = new String(recoveredContent_0_8.array()); - assertEquals("Message Payload has changed", bodyText, returnedPayloadString_0_8); - - /* - * Read back and validate the 0-10 message metadata and content - */ - StorableMessageMetaData storeableMMD_0_10 = reopenedBdbStore.getMessageMetaData(messageid_0_10); - - assertEquals("Unexpected message type", MessageMetaDataType_0_10.TYPE, storeableMMD_0_10.getType().ordinal()); - assertTrue("Unexpected instance type", storeableMMD_0_10 instanceof MessageMetaData_0_10); - MessageMetaData_0_10 returnedMMD_0_10 = (MessageMetaData_0_10) storeableMMD_0_10; - - assertEquals("Message arrival time has changed", origArrivalTime_0_10, returnedMMD_0_10.getArrivalTime()); - - DeliveryProperties returnedDelProps_0_10 = returnedMMD_0_10.getHeader().getDeliveryProperties(); - assertNotNull("DeliveryProperties were not returned", returnedDelProps_0_10); - assertEquals("Immediate flag has changed", delProps_0_10.getImmediate(), returnedDelProps_0_10.getImmediate()); - assertEquals("Routing key has changed", delProps_0_10.getRoutingKey(), returnedDelProps_0_10.getRoutingKey()); - assertEquals("Message exchange has changed", delProps_0_10.getExchange(), returnedDelProps_0_10.getExchange()); - assertEquals("Message expiration has changed", delProps_0_10.getExpiration(), returnedDelProps_0_10.getExpiration()); - assertEquals("Message delivery priority has changed", delProps_0_10.getPriority(), returnedDelProps_0_10.getPriority()); - - MessageProperties returnedMsgProps = returnedMMD_0_10.getHeader().getMessageProperties(); - assertNotNull("MessageProperties were not returned", returnedMsgProps); - assertTrue("Message correlationID has changed", Arrays.equals(msgProps_0_10.getCorrelationId(), returnedMsgProps.getCorrelationId())); - assertEquals("Message content length has changed", msgProps_0_10.getContentLength(), returnedMsgProps.getContentLength()); - assertEquals("Message content type has changed", msgProps_0_10.getContentType(), returnedMsgProps.getContentType()); - - ByteBuffer recoveredContent = ByteBuffer.allocate((int) msgProps_0_10.getContentLength()) ; - long recoveredCount = reopenedBdbStore.getContent(messageid_0_10, 0, recoveredContent); - assertEquals("Incorrect amount of payload data recovered", msgProps_0_10.getContentLength(), recoveredCount); - - String returnedPayloadString_0_10 = new String(recoveredContent.array()); - assertEquals("Message Payload has changed", bodyText, returnedPayloadString_0_10); - - reopenedBdbStore.closeMessageStore(); - } - - private DeliveryProperties createDeliveryProperties_0_10() - { - DeliveryProperties delProps_0_10 = new DeliveryProperties(); - - delProps_0_10.setDeliveryMode(MessageDeliveryMode.PERSISTENT); - delProps_0_10.setImmediate(true); - delProps_0_10.setExchange("exchange12345"); - delProps_0_10.setRoutingKey("routingKey12345"); - delProps_0_10.setExpiration(5); - delProps_0_10.setPriority(MessageDeliveryPriority.ABOVE_AVERAGE); - - return delProps_0_10; - } - - private MessageProperties createMessageProperties_0_10(int bodySize) - { - MessageProperties msgProps_0_10 = new MessageProperties(); - msgProps_0_10.setContentLength(bodySize); - msgProps_0_10.setCorrelationId("qwerty".getBytes()); - msgProps_0_10.setContentType("text/html"); - - return msgProps_0_10; - } - - - private MessagePublishInfo createPublishInfoBody_0_8() - { - return new MessagePublishInfo(new AMQShortString("exchange12345"), false, true, - new AMQShortString("routingKey12345")); - - } - - private ContentHeaderBody createContentHeaderBody_0_8(BasicContentHeaderProperties props, int length) - { - return new ContentHeaderBody(props, length); - } - - private BasicContentHeaderProperties createContentHeaderProperties_0_8() - { - BasicContentHeaderProperties props = new BasicContentHeaderProperties(); - props.setDeliveryMode(Integer.valueOf(BasicContentHeaderProperties.PERSISTENT).byteValue()); - props.setContentType("text/html"); - props.getHeaders().setString("Test", "MST"); - return props; - } - - public void testGetContentWithOffset() throws Exception - { - BDBMessageStore bdbStore = (BDBMessageStore) getStore(); - StoredMessage<MessageMetaData> storedMessage_0_8 = createAndStoreSingleChunkMessage_0_8(bdbStore); - long messageid_0_8 = storedMessage_0_8.getMessageNumber(); - - // normal case: offset is 0 - ByteBuffer dst = ByteBuffer.allocate(10); - int length = bdbStore.getContent(messageid_0_8, 0, dst); - assertEquals("Unexpected length", CONTENT_BYTES.length, length); - byte[] array = dst.array(); - assertTrue("Unexpected content", Arrays.equals(CONTENT_BYTES, array)); - - // offset is in the middle - dst = ByteBuffer.allocate(10); - length = bdbStore.getContent(messageid_0_8, 5, dst); - assertEquals("Unexpected length", 5, length); - array = dst.array(); - byte[] expected = new byte[10]; - System.arraycopy(CONTENT_BYTES, 5, expected, 0, 5); - assertTrue("Unexpected content", Arrays.equals(expected, array)); - - // offset beyond the content length - dst = ByteBuffer.allocate(10); - try - { - bdbStore.getContent(messageid_0_8, 15, dst); - fail("Should fail for the offset greater than message size"); - } - catch (RuntimeException e) - { - assertEquals("Unexpected exception message", "Offset 15 is greater than message size 10 for message id " - + messageid_0_8 + "!", e.getCause().getMessage()); - } - - // buffer is smaller then message size - dst = ByteBuffer.allocate(5); - length = bdbStore.getContent(messageid_0_8, 0, dst); - assertEquals("Unexpected length", 5, length); - array = dst.array(); - expected = new byte[5]; - System.arraycopy(CONTENT_BYTES, 0, expected, 0, 5); - assertTrue("Unexpected content", Arrays.equals(expected, array)); - - // buffer is smaller then message size, offset is not 0 - dst = ByteBuffer.allocate(5); - length = bdbStore.getContent(messageid_0_8, 2, dst); - assertEquals("Unexpected length", 5, length); - array = dst.array(); - expected = new byte[5]; - System.arraycopy(CONTENT_BYTES, 2, expected, 0, 5); - assertTrue("Unexpected content", Arrays.equals(expected, array)); - } - - /** - * Tests that messages which are added to the store and then removed using the - * public MessageStore interfaces are actually removed from the store by then - * interrogating the store with its own implementation methods and verifying - * expected exceptions are thrown to indicate the message is not present. - */ - public void testMessageCreationAndRemoval() throws Exception - { - BDBMessageStore bdbStore = (BDBMessageStore) getStore(); - - StoredMessage<MessageMetaData> storedMessage_0_8 = createAndStoreSingleChunkMessage_0_8(bdbStore); - long messageid_0_8 = storedMessage_0_8.getMessageNumber(); - - bdbStore.removeMessage(messageid_0_8, true); - - //verify the removal using the BDB store implementation methods directly - try - { - // the next line should throw since the message id should not be found - bdbStore.getMessageMetaData(messageid_0_8); - fail("No exception thrown when message id not found getting metadata"); - } - catch (StoreException e) - { - // pass since exception expected - } - - //expecting no content, allocate a 1 byte - ByteBuffer dst = ByteBuffer.allocate(1); - - assertEquals("Retrieved content when none was expected", - 0, bdbStore.getContent(messageid_0_8, 0, dst)); - } - - private StoredMessage<MessageMetaData> createAndStoreSingleChunkMessage_0_8(MessageStore store) - { - ByteBuffer chunk1 = ByteBuffer.wrap(CONTENT_BYTES); - - int bodySize = CONTENT_BYTES.length; - - //create and store the message using the MessageStore interface - MessagePublishInfo pubInfoBody_0_8 = createPublishInfoBody_0_8(); - BasicContentHeaderProperties props_0_8 = createContentHeaderProperties_0_8(); - - ContentHeaderBody chb_0_8 = createContentHeaderBody_0_8(props_0_8, bodySize); - - MessageMetaData messageMetaData_0_8 = new MessageMetaData(pubInfoBody_0_8, chb_0_8); - MessageHandle<MessageMetaData> storedMessage_0_8 = store.addMessage(messageMetaData_0_8); - - storedMessage_0_8.addContent(chunk1); - ((AbstractBDBMessageStore.StoredBDBMessage)storedMessage_0_8).flushToStore(); - - return storedMessage_0_8.allContentAdded(); - } - - public void testOnDelete() throws Exception - { - String storeLocation = getStore().getStoreLocation(); - - File location = new File(storeLocation); - assertTrue("Store does not exist at " + storeLocation, location.exists()); - - getStore().closeMessageStore(); - assertTrue("Store does not exist at " + storeLocation, location.exists()); - - BDBVirtualHost mockVH = mock(BDBVirtualHost.class); - String testLocation = getStore().getStoreLocation(); - when(mockVH.getStorePath()).thenReturn(testLocation); - - getStore().onDelete(mockVH); - - assertFalse("Store exists at " + storeLocation, location.exists()); - } - - - @Override - protected VirtualHost createVirtualHost() - { - _storeLocation = TMP_FOLDER + File.separator + getTestName(); - deleteStoreIfExists(); - - final BDBVirtualHost parent = mock(BDBVirtualHost.class); - when(parent.getStorePath()).thenReturn(_storeLocation); - return parent; - } - - private void deleteStoreIfExists() - { - if (_storeLocation != null) - { - File location = new File(_storeLocation); - if (location.exists()) - { - FileUtils.delete(location, true); - } - } - } - - @Override - protected MessageStore createMessageStore() - { - return new BDBMessageStore(); - } - -} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBStoreUpgradeTestPreparer.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBStoreUpgradeTestPreparer.java deleted file mode 100644 index 4b5069fec8..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBStoreUpgradeTestPreparer.java +++ /dev/null @@ -1,432 +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.util.HashMap; -import java.util.Map; - -import javax.jms.Connection; -import javax.jms.DeliveryMode; -import javax.jms.Destination; -import javax.jms.ExceptionListener; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Queue; -import javax.jms.Session; -import javax.jms.Topic; -import javax.jms.TopicConnection; -import javax.jms.TopicPublisher; -import javax.jms.TopicSession; -import javax.jms.TopicSubscriber; -import javax.management.MBeanServerConnection; -import javax.management.ObjectName; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXServiceURL; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.client.AMQConnectionFactory; -import org.apache.qpid.client.AMQDestination; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.queue.QueueArgumentsConverter; -import org.apache.qpid.url.URLSyntaxException; - -/** - * Prepares an older version brokers BDB store with the required - * contents for use in the BDBStoreUpgradeTest. - * - * NOTE: Must be used with the equivalent older version client! - * - * The store will then be used to verify that the upgraded is - * completed properly and that once upgraded it functions as - * expected with the new broker. - * - */ -public class BDBStoreUpgradeTestPreparer -{ - private static final Logger _logger = LoggerFactory.getLogger(BDBStoreUpgradeTestPreparer.class); - - public static final String TOPIC_NAME="myUpgradeTopic"; - public static final String SUB_NAME="myDurSubName"; - public static final String SELECTOR_SUB_NAME="mySelectorDurSubName"; - public static final String SELECTOR_TOPIC_NAME="mySelectorUpgradeTopic"; - public static final String QUEUE_NAME="myUpgradeQueue"; - public static final String NON_DURABLE_QUEUE_NAME="queue-non-durable"; - - public static final String PRIORITY_QUEUE_NAME="myPriorityQueue"; - public static final String QUEUE_WITH_DLQ_NAME="myQueueWithDLQ"; - public static final String NONEXCLUSIVE_WITH_ERRONEOUS_OWNER = "nonexclusive-with-erroneous-owner"; - public static final String MISUSED_OWNER = "misused-owner-as-description"; - private static final String VIRTUAL_HOST_NAME = "test"; - private static final String SORTED_QUEUE_NAME = "mySortedQueue"; - private static final String SORT_KEY = "mySortKey"; - private static final String TEST_EXCHANGE_NAME = "myCustomExchange"; - private static final String TEST_QUEUE_NAME = "myCustomQueue"; - - private static AMQConnectionFactory _connFac; - private static final String CONN_URL = "amqp://guest:guest@clientid/" + VIRTUAL_HOST_NAME + "?brokerlist='tcp://localhost:5672'"; - - /** - * Create a BDBStoreUpgradeTestPreparer instance - */ - public BDBStoreUpgradeTestPreparer () throws URLSyntaxException - { - _connFac = new AMQConnectionFactory(CONN_URL); - } - - private void prepareBroker() throws Exception - { - prepareQueues(); - prepareNonDurableQueue(); - prepareDurableSubscriptionWithSelector(); - prepareDurableSubscriptionWithoutSelector(); - } - - private void prepareNonDurableQueue() throws Exception - { - Connection connection = _connFac.createConnection(); - AMQSession<?, ?> session = (AMQSession<?,?>)connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - AMQShortString queueName = new AMQShortString(NON_DURABLE_QUEUE_NAME); - AMQDestination destination = (AMQDestination) session.createQueue(NON_DURABLE_QUEUE_NAME); - session.sendCreateQueue(queueName, false, false, false, null); - session.bindQueue(queueName, queueName, null, new AMQShortString("amq.direct"), destination); - MessageProducer messageProducer = session.createProducer(destination); - sendMessages(session, messageProducer, destination, DeliveryMode.PERSISTENT, 1024, 3); - connection.close(); - } - - /** - * Prepare a queue for use in testing message and binding recovery - * after the upgrade is performed. - * - * - Create a transacted session on the connection. - * - Use a consumer to create the (durable by default) queue. - * - Send 5 large messages to test (multi-frame) content recovery. - * - Send 1 small message to test (single-frame) content recovery. - * - Commit the session. - * - Send 5 small messages to test that uncommitted messages are not recovered. - * following the upgrade. - * - Close the session. - */ - private void prepareQueues() throws Exception - { - // Create a connection - Connection connection = _connFac.createConnection(); - connection.start(); - connection.setExceptionListener(new ExceptionListener() - { - public void onException(JMSException e) - { - _logger.error("Error setting exception listener for connection", e); - } - }); - // Create a session on the connection, transacted to confirm delivery - Session session = connection.createSession(true, Session.SESSION_TRANSACTED); - Queue queue = session.createQueue(QUEUE_NAME); - // Create a consumer to ensure the queue gets created - // (and enter it into the store, as queues are made durable by default) - MessageConsumer messageConsumer = session.createConsumer(queue); - messageConsumer.close(); - - // Create a Message priorityQueueProducer - MessageProducer messageProducer = session.createProducer(queue); - - // Publish 5 persistent messages, 256k chars to ensure they are multi-frame - sendMessages(session, messageProducer, queue, DeliveryMode.PERSISTENT, 256*1024, 5); - // Publish 5 persistent messages, 1k chars to ensure they are single-frame - sendMessages(session, messageProducer, queue, DeliveryMode.PERSISTENT, 1*1024, 5); - - session.commit(); - - // Publish 5 persistent messages which will NOT be committed and so should be 'lost' - sendMessages(session, messageProducer, queue, DeliveryMode.PERSISTENT, 1*1024, 5); - messageProducer.close(); - session.close(); - - session = connection.createSession(true, Session.SESSION_TRANSACTED); - // Create a priority queue on broker - final Map<String,Object> priorityQueueArguments = new HashMap<String, Object>(); - priorityQueueArguments.put(QueueArgumentsConverter.X_QPID_PRIORITIES,10); - Queue priorityQueue = createAndBindQueueOnBroker(session, PRIORITY_QUEUE_NAME, priorityQueueArguments); - MessageProducer priorityQueueProducer = session.createProducer(priorityQueue); - - for (int msg = 0; msg < 5; msg++) - { - priorityQueueProducer.setPriority(msg % 10); - Message message = session.createTextMessage(generateString(256*1024)); - message.setIntProperty("ID", msg); - priorityQueueProducer.send(message); - } - session.commit(); - priorityQueueProducer.close(); - - // Create a queue that has a DLQ - final Map<String,Object> queueWithDLQArguments = new HashMap<String, Object>(); - queueWithDLQArguments.put("x-qpid-dlq-enabled", true); - queueWithDLQArguments.put("x-qpid-maximum-delivery-count", 2); - createAndBindQueueOnBroker(session, QUEUE_WITH_DLQ_NAME, queueWithDLQArguments); - - // Send message to the DLQ - Queue dlq = session.createQueue("fanout://" + QUEUE_WITH_DLQ_NAME + "_DLE//does-not-matter"); - MessageProducer dlqMessageProducer = session.createProducer(dlq); - sendMessages(session, dlqMessageProducer, dlq, DeliveryMode.PERSISTENT, 1*1024, 1); - session.commit(); - - // Create a queue with JMX specifying an owner, so it can later be moved into description - createAndBindQueueOnBrokerWithJMX(NONEXCLUSIVE_WITH_ERRONEOUS_OWNER, MISUSED_OWNER, priorityQueueArguments); - - createExchange(TEST_EXCHANGE_NAME, "direct"); - Queue customQueue = createAndBindQueueOnBroker(session, TEST_QUEUE_NAME, null, TEST_EXCHANGE_NAME, "direct"); - MessageProducer customQueueMessageProducer = session.createProducer(customQueue); - sendMessages(session, customQueueMessageProducer, customQueue, DeliveryMode.PERSISTENT, 1*1024, 1); - session.commit(); - customQueueMessageProducer.close(); - - prepareSortedQueue(session, SORTED_QUEUE_NAME, SORT_KEY); - - session.close(); - connection.close(); - } - - private Queue createAndBindQueueOnBroker(Session session, String queueName, final Map<String, Object> arguments) throws Exception - { - return createAndBindQueueOnBroker(session, queueName, arguments, "amq.direct", "direct"); - } - - private Queue createAndBindQueueOnBroker(Session session, String queueName, final Map<String, Object> arguments, String exchangeName, String exchangeType) throws Exception - { - ((AMQSession<?,?>) session).createQueue(new AMQShortString(queueName), false, true, false, arguments); - Queue queue = session.createQueue("BURL:" + exchangeType + "://" + exchangeName + "/" + queueName + "/" + queueName + "?durable='true'"); - ((AMQSession<?,?>) session).declareAndBind((AMQDestination)queue); - return queue; - } - - private void createAndBindQueueOnBrokerWithJMX(String queueName, String owner, final Map<String, Object> arguments) throws Exception - { - JMXConnector jmxConnector = createJMXConnector(); - try - { - MBeanServerConnection mbsc = jmxConnector.getMBeanServerConnection(); - ObjectName virtualHost = new ObjectName("org.apache.qpid:type=VirtualHost.VirtualHostManager,VirtualHost=\"" + VIRTUAL_HOST_NAME + "\""); - - Object[] params = new Object[] {queueName, owner, true, arguments}; - String[] signature = new String[] {String.class.getName(), String.class.getName(), boolean.class.getName(), Map.class.getName()}; - mbsc.invoke(virtualHost, "createNewQueue", params, signature); - - ObjectName directExchange = new ObjectName("org.apache.qpid:type=VirtualHost.Exchange,VirtualHost=\"" + VIRTUAL_HOST_NAME + "\",name=\"amq.direct\",ExchangeType=direct"); - mbsc.invoke(directExchange, "createNewBinding", new Object[] {queueName, queueName}, new String[] {String.class.getName(), String.class.getName()}); - } - finally - { - jmxConnector.close(); - } - } - - private void createExchange(String exchangeName, String exchangeType) throws Exception - { - JMXConnector jmxConnector = createJMXConnector(); - try - { - MBeanServerConnection mbsc = jmxConnector.getMBeanServerConnection(); - ObjectName virtualHost = new ObjectName("org.apache.qpid:type=VirtualHost.VirtualHostManager,VirtualHost=\"" + VIRTUAL_HOST_NAME + "\""); - - Object[] params = new Object[]{exchangeName, exchangeType, true}; - String[] signature = new String[]{String.class.getName(), String.class.getName(), boolean.class.getName()}; - mbsc.invoke(virtualHost, "createNewExchange", params, signature); - } - finally - { - jmxConnector.close(); - } - } - - private JMXConnector createJMXConnector() throws Exception - { - Map<String, Object> environment = new HashMap<>(); - environment.put(JMXConnector.CREDENTIALS, new String[] {"admin", "admin"}); - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:8999/jmxrmi"); - return JMXConnectorFactory.connect(url, environment); - } - - private void prepareSortedQueue(Session session, String queueName, String sortKey) throws Exception - { - final Map<String, Object> arguments = new HashMap<String, Object>(); - arguments.put("qpid.queue_sort_key", sortKey); - Queue sortedQueue = createAndBindQueueOnBroker(session, queueName, arguments); - - MessageProducer messageProducer2 = session.createProducer(sortedQueue); - - String[] sortKeys = {"c", "b", "e", "a", "d"}; - for (int i = 1; i <= sortKeys.length; i++) - { - Message message = session.createTextMessage(generateString(256*1024)); - message.setIntProperty("ID", i); - message.setStringProperty(sortKey, sortKeys[i - 1]); - messageProducer2.send(message); - } - session.commit(); - } - - /** - * Prepare a DurableSubscription backing queue for use in testing selector - * recovery and queue exclusivity marking during the upgrade process. - * - * - Create a transacted session on the connection. - * - Open and close a DurableSubscription with selector to create the backing queue. - * - Send a message which matches the selector. - * - Send a message which does not match the selector. - * - Send a message which matches the selector but will remain uncommitted. - * - Close the session. - */ - private void prepareDurableSubscriptionWithSelector() throws Exception - { - - // Create a connection - TopicConnection connection = _connFac.createTopicConnection(); - connection.start(); - connection.setExceptionListener(new ExceptionListener() - { - public void onException(JMSException e) - { - _logger.error("Error setting exception listener for connection", e); - } - }); - // Create a session on the connection, transacted to confirm delivery - Session session = connection.createSession(true, Session.SESSION_TRANSACTED); - Topic topic = session.createTopic(SELECTOR_TOPIC_NAME); - - // Create and register a durable subscriber with selector and then close it - TopicSubscriber durSub1 = session.createDurableSubscriber(topic, SELECTOR_SUB_NAME,"testprop='true'", false); - durSub1.close(); - - // Create a publisher and send a persistent message which matches the selector - // followed by one that does not match, and another which matches but is not - // committed and so should be 'lost' - TopicSession pubSession = connection.createTopicSession(true, Session.SESSION_TRANSACTED); - TopicPublisher publisher = pubSession.createPublisher(topic); - - publishMessages(pubSession, publisher, topic, DeliveryMode.PERSISTENT, 1*1024, 1, "true"); - publishMessages(pubSession, publisher, topic, DeliveryMode.PERSISTENT, 1*1024, 1, "false"); - pubSession.commit(); - publishMessages(pubSession, publisher, topic, DeliveryMode.PERSISTENT, 1*1024, 1, "true"); - - publisher.close(); - pubSession.close(); - connection.close(); - } - - /** - * Prepare a DurableSubscription backing queue for use in testing use of - * DurableSubscriptions without selectors following the upgrade process. - * - * - Create a transacted session on the connection. - * - Open and close a DurableSubscription without selector to create the backing queue. - * - Send a message which matches the subscription and commit session. - * - Close the session. - */ - private void prepareDurableSubscriptionWithoutSelector() throws Exception - { - // Create a connection - TopicConnection connection = _connFac.createTopicConnection(); - connection.start(); - connection.setExceptionListener(new ExceptionListener() - { - public void onException(JMSException e) - { - _logger.error("Error setting exception listener for connection", e); - } - }); - // Create a session on the connection, transacted to confirm delivery - Session session = connection.createSession(true, Session.SESSION_TRANSACTED); - Topic topic = session.createTopic(TOPIC_NAME); - - // Create and register a durable subscriber without selector and then close it - TopicSubscriber durSub1 = session.createDurableSubscriber(topic, SUB_NAME); - durSub1.close(); - - // Create a publisher and send a persistent message which matches the subscription - TopicSession pubSession = connection.createTopicSession(true, Session.SESSION_TRANSACTED); - TopicPublisher publisher = pubSession.createPublisher(topic); - - publishMessages(pubSession, publisher, topic, DeliveryMode.PERSISTENT, 1*1024, 1, "indifferent"); - pubSession.commit(); - - publisher.close(); - pubSession.close(); - connection.close(); - } - - private static void sendMessages(Session session, MessageProducer messageProducer, - Destination dest, int deliveryMode, int length, int numMesages) throws JMSException - { - for (int i = 1; i <= numMesages; i++) - { - Message message = session.createTextMessage(generateString(length)); - message.setIntProperty("ID", i); - messageProducer.send(message, deliveryMode, Message.DEFAULT_PRIORITY, Message.DEFAULT_TIME_TO_LIVE); - } - } - - private static void publishMessages(Session session, TopicPublisher publisher, - Destination dest, int deliveryMode, int length, int numMesages, String selectorProperty) throws JMSException - { - for (int i = 1; i <= numMesages; i++) - { - Message message = session.createTextMessage(generateString(length)); - message.setIntProperty("ID", i); - message.setStringProperty("testprop", selectorProperty); - publisher.publish(message, deliveryMode, Message.DEFAULT_PRIORITY, Message.DEFAULT_TIME_TO_LIVE); - } - } - - /** - * Generates a string of a given length consisting of the sequence 0,1,2,..,9,0,1,2. - * - * @param length number of characters in the string - * @return string sequence of the given length - */ - private static String generateString(int length) - { - char[] base_chars = new char[]{'0','1','2','3','4','5','6','7','8','9'}; - char[] chars = new char[length]; - for (int i = 0; i < (length); i++) - { - chars[i] = base_chars[i % 10]; - } - return new String(chars); - } - - /** - * Run the preparation tool. - * @param args Command line arguments. - */ - public static void main(String[] args) throws Exception - { - System.setProperty("qpid.dest_syntax", "BURL"); - BDBStoreUpgradeTestPreparer producer = new BDBStoreUpgradeTestPreparer(); - producer.prepareBroker(); - } -} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/EnvHomeRegistryTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/EnvHomeRegistryTest.java deleted file mode 100644 index 5de51df992..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/EnvHomeRegistryTest.java +++ /dev/null @@ -1,68 +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 junit.framework.TestCase; - -import org.apache.qpid.test.utils.QpidTestCase; - -public class EnvHomeRegistryTest extends TestCase -{ - - private final EnvHomeRegistry _ehr = new EnvHomeRegistry(); - - public void testDuplicateEnvHomeRejected() throws Exception - { - File home = new File(QpidTestCase.TMP_FOLDER, getName()); - - _ehr.registerHome(home); - try - { - _ehr.registerHome(home); - fail("Exception not thrown"); - } - catch (IllegalArgumentException iae) - { - // PASS - } - } - - public void testUniqueEnvHomesAllowed() throws Exception - { - File home1 = new File(QpidTestCase.TMP_FOLDER, getName() + "1"); - File home2 = new File(QpidTestCase.TMP_FOLDER, getName() + "2"); - - _ehr.registerHome(home1); - _ehr.registerHome(home2); - } - - public void testReuseOfEnvHomesAllowed() throws Exception - { - File home = new File(QpidTestCase.TMP_FOLDER, getName() + "1"); - - _ehr.registerHome(home); - - _ehr.deregisterHome(home); - - _ehr.registerHome(home); - } -}
\ No newline at end of file diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/NoopConfigurationChangeListener.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/NoopConfigurationChangeListener.java deleted file mode 100644 index b185a31c3b..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/NoopConfigurationChangeListener.java +++ /dev/null @@ -1,53 +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.qpid.server.model.ConfigurationChangeListener; -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.model.State; - -public class NoopConfigurationChangeListener implements ConfigurationChangeListener -{ - - public NoopConfigurationChangeListener() { - } - - @Override - public void stateChanged(ConfiguredObject<?> object, State oldState, State newState) - { - } - - @Override - public void childAdded(ConfiguredObject<?> object, ConfiguredObject<?> child) - { - } - - @Override - public void childRemoved(ConfiguredObject<?> object, ConfiguredObject<?> child) - { - } - - @Override - public void attributeSet(ConfiguredObject<?> object, String attributeName, Object oldAttributeValue, - Object newAttributeValue) - { - } -} 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 deleted file mode 100644 index 3403ec53dc..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacadeTest.java +++ /dev/null @@ -1,153 +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 static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.io.File; -import java.util.Collections; -import java.util.Map; - -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; -import com.sleepycat.je.EnvironmentConfig; - -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 = createEnvironmentFacade(); - assertNotNull("Environment should not be null", ef); - Environment e = ef.getEnvironment(); - assertTrue("Environment is not valid", e.isValid()); - } - - public void testSecondEnvironmentFacadeUsingSamePathRejected() throws Exception - { - EnvironmentFacade ef = createEnvironmentFacade(); - assertNotNull("Environment should not be null", ef); - try - { - createEnvironmentFacade(); - fail("Exception not thrown"); - } - catch (IllegalArgumentException iae) - { - // PASS - } - - ef.close(); - - EnvironmentFacade ef2 = createEnvironmentFacade(); - assertNotNull("Environment should not be null", ef2); - } - - public void testClose() throws Exception - { - EnvironmentFacade ef = createEnvironmentFacade(); - ef.close(); - Environment e = ef.getEnvironment(); - - assertNull("Environment should be null after facade close", e); - } - - public void testOverrideJeParameter() throws Exception - { - String statCollectVarName = EnvironmentConfig.STATS_COLLECT; - - EnvironmentFacade ef = createEnvironmentFacade(); - assertEquals("false", ef.getEnvironment().getMutableConfig().getConfigParam(statCollectVarName)); - ef.close(); - - ef = createEnvironmentFacade(Collections.singletonMap(statCollectVarName, "true")); - assertEquals("true", ef.getEnvironment().getMutableConfig().getConfigParam(statCollectVarName)); - ef.close(); - } - - - public void testOpenDatabaseReusesCachedHandle() throws Exception - { - DatabaseConfig createIfAbsentDbConfig = DatabaseConfig.DEFAULT.setAllowCreate(true); - - EnvironmentFacade ef = createEnvironmentFacade(); - Database handle1 = ef.openDatabase("myDatabase", createIfAbsentDbConfig); - assertNotNull(handle1); - - Database handle2 = ef.openDatabase("myDatabase", createIfAbsentDbConfig); - assertSame("Database handle should be cached", handle1, handle2); - - ef.closeDatabase("myDatabase"); - - Database handle3 = ef.openDatabase("myDatabase", createIfAbsentDbConfig); - assertNotSame("Expecting a new handle after database closure", handle1, handle3); - } - - EnvironmentFacade createEnvironmentFacade() - { - _environmentFacade = createEnvironmentFacade(Collections.<String, String>emptyMap()); - return _environmentFacade; - - } - - EnvironmentFacade createEnvironmentFacade(Map<String, String> map) - { - StandardEnvironmentConfiguration sec = mock(StandardEnvironmentConfiguration.class); - when(sec.getName()).thenReturn(getTestName()); - when(sec.getParameters()).thenReturn(map); - when(sec.getStorePath()).thenReturn(_storePath.getAbsolutePath()); - - return new StandardEnvironmentFacade(sec); - } - -} 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 deleted file mode 100644 index b8c3b493bc..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacadeTest.java +++ /dev/null @@ -1,1057 +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.replication; - -import static org.mockito.Matchers.anyInt; -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.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -import com.sleepycat.bind.tuple.IntegerBinding; -import com.sleepycat.bind.tuple.StringBinding; -import com.sleepycat.je.Database; -import com.sleepycat.je.DatabaseConfig; -import com.sleepycat.je.DatabaseEntry; -import com.sleepycat.je.Durability; -import com.sleepycat.je.Environment; -import com.sleepycat.je.EnvironmentConfig; -import com.sleepycat.je.Transaction; -import com.sleepycat.je.rep.NodeState; -import com.sleepycat.je.rep.ReplicaWriteException; -import com.sleepycat.je.rep.ReplicatedEnvironment; -import com.sleepycat.je.rep.ReplicatedEnvironment.State; -import com.sleepycat.je.rep.ReplicationConfig; -import com.sleepycat.je.rep.ReplicationNode; -import com.sleepycat.je.rep.StateChangeEvent; -import com.sleepycat.je.rep.StateChangeListener; -import org.codehaus.jackson.map.ObjectMapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.server.store.berkeleydb.EnvironmentFacade; -import org.apache.qpid.server.util.ConnectionScopedRuntimeException; -import org.apache.qpid.test.utils.PortHelper; -import org.apache.qpid.test.utils.QpidTestCase; -import org.apache.qpid.test.utils.TestFileUtils; -import org.apache.qpid.util.FileUtils; - -public class ReplicatedEnvironmentFacadeTest extends QpidTestCase -{ - private static final Logger LOGGER = LoggerFactory.getLogger(ReplicatedEnvironmentFacadeTest.class); - private static final int LISTENER_TIMEOUT = 5; - private static final int WAIT_STATE_CHANGE_TIMEOUT = 30; - - private final PortHelper _portHelper = new PortHelper(); - - private final String TEST_GROUP_NAME = "testGroupName"; - private final String TEST_NODE_NAME = "testNodeName"; - private final int TEST_NODE_PORT = _portHelper.getNextAvailable(); - private final String TEST_NODE_HOST_PORT = "localhost:" + TEST_NODE_PORT; - private final String TEST_NODE_HELPER_HOST_PORT = TEST_NODE_HOST_PORT; - private final Durability TEST_DURABILITY = Durability.parse("SYNC,NO_SYNC,SIMPLE_MAJORITY"); - private final boolean TEST_DESIGNATED_PRIMARY = false; - private final int TEST_PRIORITY = 1; - private final int TEST_ELECTABLE_GROUP_OVERRIDE = 0; - - private File _storePath; - private final Map<String, ReplicatedEnvironmentFacade> _nodes = new HashMap<String, ReplicatedEnvironmentFacade>(); - - public void setUp() throws Exception - { - super.setUp(); - - _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(); - } - } - - _portHelper.waitUntilAllocatedPortsAreFree(); - } - 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 testOpenDatabaseReusesCachedHandle() throws Exception - { - DatabaseConfig createIfAbsentDbConfig = DatabaseConfig.DEFAULT.setAllowCreate(true); - - EnvironmentFacade ef = createMaster(); - Database handle1 = ef.openDatabase("myDatabase", createIfAbsentDbConfig); - assertNotNull(handle1); - - Database handle2 = ef.openDatabase("myDatabase", createIfAbsentDbConfig); - assertSame("Database handle should be cached", handle1, handle2); - - ef.closeDatabase("myDatabase"); - - Database handle3 = ef.openDatabase("myDatabase", createIfAbsentDbConfig); - assertNotSame("Expecting a new handle after database closure", handle1, handle3); - } - - public void testOpenDatabaseWhenFacadeIsNotOpened() throws Exception - { - DatabaseConfig createIfAbsentDbConfig = DatabaseConfig.DEFAULT.setAllowCreate(true); - - EnvironmentFacade ef = createMaster(); - ef.close(); - - try - { - ef.openDatabase("myDatabase", createIfAbsentDbConfig ); - fail("Database open should fail"); - } - catch(ConnectionScopedRuntimeException e) - { - assertEquals("Unexpected exception", "Environment facade is not in opened state", 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 testSetMessageStoreDurability() throws Exception - { - ReplicatedEnvironmentFacade master = createMaster(); - assertEquals("Unexpected message store durability", - new Durability(Durability.SyncPolicy.NO_SYNC, Durability.SyncPolicy.NO_SYNC, Durability.ReplicaAckPolicy.SIMPLE_MAJORITY), - master.getRealMessageStoreDurability()); - assertEquals("Unexpected durability", TEST_DURABILITY, master.getMessageStoreDurability()); - assertTrue("Unexpected coalescing sync", master.isCoalescingSync()); - - master.setMessageStoreDurability(Durability.SyncPolicy.WRITE_NO_SYNC, Durability.SyncPolicy.SYNC, Durability.ReplicaAckPolicy.ALL); - assertEquals("Unexpected message store durability", - new Durability(Durability.SyncPolicy.WRITE_NO_SYNC, Durability.SyncPolicy.SYNC, Durability.ReplicaAckPolicy.ALL), - master.getRealMessageStoreDurability()); - assertFalse("Coalescing sync committer is still running", master.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 testReplicationGroupListenerHearsAboutExistingRemoteReplicationNodes() throws Exception - { - ReplicatedEnvironmentFacade master = createMaster(); - String nodeName2 = TEST_NODE_NAME + "_2"; - String host = "localhost"; - int port = _portHelper.getNextAvailable(); - String node2NodeHostPort = host + ":" + port; - - final AtomicInteger invocationCount = new AtomicInteger(); - final CountDownLatch nodeRecoveryLatch = new CountDownLatch(1); - ReplicationGroupListener listener = new NoopReplicationGroupListener() - { - @Override - public void onReplicationNodeRecovered(ReplicationNode node) - { - nodeRecoveryLatch.countDown(); - invocationCount.incrementAndGet(); - } - }; - - createReplica(nodeName2, node2NodeHostPort, listener); - - assertEquals("Unexpected number of nodes", 2, master.getNumberOfElectableGroupMembers()); - - assertTrue("Listener not fired within timeout", nodeRecoveryLatch.await(LISTENER_TIMEOUT, TimeUnit.SECONDS)); - assertEquals("Unexpected number of listener invocations", 1, invocationCount.get()); - } - - public void testReplicationGroupListenerHearsNodeAdded() throws Exception - { - final CountDownLatch nodeAddedLatch = new CountDownLatch(1); - final AtomicInteger invocationCount = new AtomicInteger(); - ReplicationGroupListener listener = new NoopReplicationGroupListener() - { - @Override - public void onReplicationNodeAddedToGroup(ReplicationNode node) - { - invocationCount.getAndIncrement(); - nodeAddedLatch.countDown(); - } - }; - - TestStateChangeListener stateChangeListener = new TestStateChangeListener(State.MASTER); - ReplicatedEnvironmentFacade replicatedEnvironmentFacade = addNode(stateChangeListener, listener); - assertTrue("Master was not started", stateChangeListener.awaitForStateChange(LISTENER_TIMEOUT, TimeUnit.SECONDS)); - - assertEquals("Unexpected number of nodes at start of test", 1, replicatedEnvironmentFacade.getNumberOfElectableGroupMembers()); - - String node2Name = TEST_NODE_NAME + "_2"; - String node2NodeHostPort = "localhost" + ":" + _portHelper.getNextAvailable(); - replicatedEnvironmentFacade.setPermittedNodes(Arrays.asList(replicatedEnvironmentFacade.getHostPort(), node2NodeHostPort)); - createReplica(node2Name, node2NodeHostPort, new NoopReplicationGroupListener()); - - assertTrue("Listener not fired within timeout", nodeAddedLatch.await(LISTENER_TIMEOUT, TimeUnit.SECONDS)); - - assertEquals("Unexpected number of nodes", 2, replicatedEnvironmentFacade.getNumberOfElectableGroupMembers()); - - assertEquals("Unexpected number of listener invocations", 1, invocationCount.get()); - } - - public void testReplicationGroupListenerHearsNodeRemoved() throws Exception - { - final CountDownLatch nodeDeletedLatch = new CountDownLatch(1); - final CountDownLatch nodeAddedLatch = new CountDownLatch(1); - final AtomicInteger invocationCount = new AtomicInteger(); - ReplicationGroupListener listener = new NoopReplicationGroupListener() - { - @Override - public void onReplicationNodeRecovered(ReplicationNode node) - { - nodeAddedLatch.countDown(); - } - - @Override - public void onReplicationNodeAddedToGroup(ReplicationNode node) - { - nodeAddedLatch.countDown(); - } - - @Override - public void onReplicationNodeRemovedFromGroup(ReplicationNode node) - { - invocationCount.getAndIncrement(); - nodeDeletedLatch.countDown(); - } - }; - - TestStateChangeListener stateChangeListener = new TestStateChangeListener(State.MASTER); - ReplicatedEnvironmentFacade replicatedEnvironmentFacade = addNode(stateChangeListener, listener); - assertTrue("Master was not started", stateChangeListener.awaitForStateChange(LISTENER_TIMEOUT, TimeUnit.SECONDS)); - - String node2Name = TEST_NODE_NAME + "_2"; - String node2NodeHostPort = "localhost" + ":" + _portHelper.getNextAvailable(); - replicatedEnvironmentFacade.setPermittedNodes(Arrays.asList(replicatedEnvironmentFacade.getHostPort(), node2NodeHostPort)); - createReplica(node2Name, node2NodeHostPort, new NoopReplicationGroupListener()); - - assertEquals("Unexpected number of nodes at start of test", 2, replicatedEnvironmentFacade.getNumberOfElectableGroupMembers()); - - // Need to await the listener hearing the addition of the node to the model. - assertTrue("Node add not fired within timeout", nodeAddedLatch.await(LISTENER_TIMEOUT, TimeUnit.SECONDS)); - - // Now remove the node and ensure we hear the event - replicatedEnvironmentFacade.removeNodeFromGroup(node2Name); - - assertTrue("Node delete not fired within timeout", nodeDeletedLatch.await(LISTENER_TIMEOUT, TimeUnit.SECONDS)); - - assertEquals("Unexpected number of nodes after node removal", 1, replicatedEnvironmentFacade.getNumberOfElectableGroupMembers()); - - assertEquals("Unexpected number of listener invocations", 1, invocationCount.get()); - } - - public void testMasterHearsRemoteNodeRoles() throws Exception - { - final String node2Name = TEST_NODE_NAME + "_2"; - final CountDownLatch nodeAddedLatch = new CountDownLatch(1); - final AtomicReference<ReplicationNode> nodeRef = new AtomicReference<ReplicationNode>(); - final CountDownLatch stateLatch = new CountDownLatch(1); - final AtomicReference<NodeState> stateRef = new AtomicReference<NodeState>(); - ReplicationGroupListener listener = new NoopReplicationGroupListener() - { - @Override - public void onReplicationNodeAddedToGroup(ReplicationNode node) - { - nodeRef.set(node); - nodeAddedLatch.countDown(); - } - - @Override - public void onNodeState(ReplicationNode node, NodeState nodeState) - { - if (node2Name.equals(node.getName())) - { - stateRef.set(nodeState); - stateLatch.countDown(); - } - } - }; - - TestStateChangeListener stateChangeListener = new TestStateChangeListener(State.MASTER); - ReplicatedEnvironmentFacade replicatedEnvironmentFacade = addNode(stateChangeListener, listener); - assertTrue("Master was not started", stateChangeListener.awaitForStateChange(LISTENER_TIMEOUT, TimeUnit.SECONDS)); - - String node2NodeHostPort = "localhost" + ":" + _portHelper.getNextAvailable(); - replicatedEnvironmentFacade.setPermittedNodes(Arrays.asList(replicatedEnvironmentFacade.getHostPort(), node2NodeHostPort)); - createReplica(node2Name, node2NodeHostPort, new NoopReplicationGroupListener()); - - assertEquals("Unexpected number of nodes at start of test", 2, replicatedEnvironmentFacade.getNumberOfElectableGroupMembers()); - - assertTrue("Node add not fired within timeout", nodeAddedLatch.await(LISTENER_TIMEOUT, TimeUnit.SECONDS)); - - ReplicationNode remoteNode = (ReplicationNode)nodeRef.get(); - assertEquals("Unexpected node name", node2Name, remoteNode.getName()); - - assertTrue("Node state not fired within timeout", stateLatch.await(LISTENER_TIMEOUT, TimeUnit.SECONDS)); - assertEquals("Unexpected node state", State.REPLICA, stateRef.get().getNodeState()); - } - - public void testRemoveNodeFromGroup() throws Exception - { - TestStateChangeListener stateChangeListener = new TestStateChangeListener(State.MASTER); - ReplicatedEnvironmentFacade environmentFacade = addNode(TEST_NODE_NAME, TEST_NODE_HOST_PORT, true, stateChangeListener, new NoopReplicationGroupListener()); - assertTrue("Environment was not created", stateChangeListener.awaitForStateChange(LISTENER_TIMEOUT, TimeUnit.SECONDS)); - - - String node2Name = TEST_NODE_NAME + "_2"; - String node2NodeHostPort = "localhost:" + _portHelper.getNextAvailable(); - ReplicatedEnvironmentFacade ref2 = createReplica(node2Name, node2NodeHostPort, new NoopReplicationGroupListener()); - - assertEquals("Unexpected group members count", 2, environmentFacade.getNumberOfElectableGroupMembers()); - ref2.close(); - - environmentFacade.removeNodeFromGroup(node2Name); - assertEquals("Unexpected group members count", 1, environmentFacade.getNumberOfElectableGroupMembers()); - } - - - public void testEnvironmentFacadeDetectsRemovalOfRemoteNode() throws Exception - { - final String replicaName = TEST_NODE_NAME + "_1"; - final CountDownLatch nodeRemovedLatch = new CountDownLatch(1); - final CountDownLatch nodeAddedLatch = new CountDownLatch(1); - final AtomicReference<ReplicationNode> addedNodeRef = new AtomicReference<ReplicationNode>(); - final AtomicReference<ReplicationNode> removedNodeRef = new AtomicReference<ReplicationNode>(); - final CountDownLatch stateLatch = new CountDownLatch(1); - final AtomicReference<NodeState> stateRef = new AtomicReference<NodeState>(); - - ReplicationGroupListener listener = new NoopReplicationGroupListener() - { - @Override - public void onReplicationNodeAddedToGroup(ReplicationNode node) - { - if (addedNodeRef.compareAndSet(null, node)) - { - nodeAddedLatch.countDown(); - } - } - - @Override - public void onReplicationNodeRemovedFromGroup(ReplicationNode node) - { - removedNodeRef.set(node); - nodeRemovedLatch.countDown(); - } - - @Override - public void onNodeState(ReplicationNode node, NodeState nodeState) - { - if (replicaName.equals(node.getName())) - { - stateRef.set(nodeState); - stateLatch.countDown(); - } - } - }; - - TestStateChangeListener stateChangeListener = new TestStateChangeListener(State.MASTER); - final ReplicatedEnvironmentFacade masterEnvironment = addNode(stateChangeListener, listener); - assertTrue("Master was not started", stateChangeListener.awaitForStateChange(LISTENER_TIMEOUT, TimeUnit.SECONDS)); - - masterEnvironment.setDesignatedPrimary(true); - - int replica1Port = _portHelper.getNextAvailable(); - String node1NodeHostPort = "localhost:" + replica1Port; - masterEnvironment.setPermittedNodes(Arrays.asList(masterEnvironment.getHostPort(), node1NodeHostPort)); - ReplicatedEnvironmentFacade replica = createReplica(replicaName, node1NodeHostPort, new NoopReplicationGroupListener()); - - assertTrue("Node should be added", nodeAddedLatch.await(WAIT_STATE_CHANGE_TIMEOUT, TimeUnit.SECONDS)); - - ReplicationNode node = addedNodeRef.get(); - assertEquals("Unexpected node name", replicaName, node.getName()); - - assertTrue("Node state was not heard", stateLatch.await(WAIT_STATE_CHANGE_TIMEOUT, TimeUnit.SECONDS)); - assertEquals("Unexpected node role", State.REPLICA, stateRef.get().getNodeState()); - assertEquals("Unexpected node name", replicaName, stateRef.get().getNodeName()); - - replica.close(); - masterEnvironment.removeNodeFromGroup(node.getName()); - - assertTrue("Node deleting is undetected by the environment facade", nodeRemovedLatch.await(WAIT_STATE_CHANGE_TIMEOUT, TimeUnit.SECONDS)); - assertEquals("Unexpected node is deleted", node, removedNodeRef.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()); - } - - 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(stateChangeListener, new NoopReplicationGroupListener()); - assertTrue("Master was not started", masterLatch.await(LISTENER_TIMEOUT, TimeUnit.SECONDS)); - - int replica1Port = _portHelper.getNextAvailable(); - String node1NodeHostPort = "localhost:" + replica1Port; - int replica2Port = _portHelper.getNextAvailable(); - String node2NodeHostPort = "localhost:" + replica2Port; - - ReplicatedEnvironmentFacade replica1 = createReplica(TEST_NODE_NAME + "_1", node1NodeHostPort, new NoopReplicationGroupListener()); - ReplicatedEnvironmentFacade replica2 = createReplica(TEST_NODE_NAME + "_2", node2NodeHostPort, new NoopReplicationGroupListener()); - - // 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 testTransferMasterToSelf() throws Exception - { - final CountDownLatch firstNodeReplicaStateLatch = new CountDownLatch(1); - final CountDownLatch firstNodeMasterStateLatch = new CountDownLatch(1); - StateChangeListener stateChangeListener = new StateChangeListener(){ - - @Override - public void stateChange(StateChangeEvent event) throws RuntimeException - { - ReplicatedEnvironment.State state = event.getState(); - if (state == ReplicatedEnvironment.State.REPLICA) - { - firstNodeReplicaStateLatch.countDown(); - } - if (state == ReplicatedEnvironment.State.MASTER) - { - firstNodeMasterStateLatch.countDown(); - } - } - }; - ReplicatedEnvironmentFacade firstNode = addNode(stateChangeListener, new NoopReplicationGroupListener()); - assertTrue("Environment did not become a master", firstNodeMasterStateLatch.await(10, TimeUnit.SECONDS)); - - int replica1Port = _portHelper.getNextAvailable(); - String node1NodeHostPort = "localhost:" + replica1Port; - ReplicatedEnvironmentFacade secondNode = createReplica(TEST_NODE_NAME + "_1", node1NodeHostPort, new NoopReplicationGroupListener()); - assertEquals("Unexpected state", ReplicatedEnvironment.State.REPLICA.name(), secondNode.getNodeState()); - - int replica2Port = _portHelper.getNextAvailable(); - String node2NodeHostPort = "localhost:" + replica2Port; - final CountDownLatch replicaStateLatch = new CountDownLatch(1); - final CountDownLatch masterStateLatch = new CountDownLatch(1); - StateChangeListener testStateChangeListener = new StateChangeListener() - { - @Override - public void stateChange(StateChangeEvent event) throws RuntimeException - { - ReplicatedEnvironment.State state = event.getState(); - if (state == ReplicatedEnvironment.State.REPLICA) - { - replicaStateLatch.countDown(); - } - if (state == ReplicatedEnvironment.State.MASTER) - { - masterStateLatch.countDown(); - } - } - }; - ReplicatedEnvironmentFacade thirdNode = addNode(TEST_NODE_NAME + "_2", node2NodeHostPort, TEST_DESIGNATED_PRIMARY, - testStateChangeListener, new NoopReplicationGroupListener()); - assertTrue("Environment did not become a replica", replicaStateLatch.await(10, TimeUnit.SECONDS)); - assertEquals(3, thirdNode.getNumberOfElectableGroupMembers()); - - thirdNode.transferMasterToSelfAsynchronously(); - assertTrue("Environment did not become a master", masterStateLatch.await(10, TimeUnit.SECONDS)); - assertTrue("First node environment did not become a replica", firstNodeReplicaStateLatch.await(10, TimeUnit.SECONDS)); - assertEquals("Unexpected state", ReplicatedEnvironment.State.REPLICA.name(), firstNode.getNodeState()); - } - - public void testTransferMasterAnotherNode() throws Exception - { - final CountDownLatch firstNodeReplicaStateLatch = new CountDownLatch(1); - final CountDownLatch firstNodeMasterStateLatch = new CountDownLatch(1); - StateChangeListener stateChangeListener = new StateChangeListener(){ - - @Override - public void stateChange(StateChangeEvent event) throws RuntimeException - { - ReplicatedEnvironment.State state = event.getState(); - if (state == ReplicatedEnvironment.State.REPLICA) - { - firstNodeReplicaStateLatch.countDown(); - } - if (state == ReplicatedEnvironment.State.MASTER) - { - firstNodeMasterStateLatch.countDown(); - } - } - }; - ReplicatedEnvironmentFacade firstNode = addNode(stateChangeListener, new NoopReplicationGroupListener()); - assertTrue("Environment did not become a master", firstNodeMasterStateLatch.await(10, TimeUnit.SECONDS)); - - int replica1Port = _portHelper.getNextAvailable(); - String node1NodeHostPort = "localhost:" + replica1Port; - ReplicatedEnvironmentFacade secondNode = createReplica(TEST_NODE_NAME + "_1", node1NodeHostPort, new NoopReplicationGroupListener()); - assertEquals("Unexpected state", ReplicatedEnvironment.State.REPLICA.name(), secondNode.getNodeState()); - - int replica2Port = _portHelper.getNextAvailable(); - String node2NodeHostPort = "localhost:" + replica2Port; - final CountDownLatch replicaStateLatch = new CountDownLatch(1); - final CountDownLatch masterStateLatch = new CountDownLatch(1); - StateChangeListener testStateChangeListener = new StateChangeListener() - { - @Override - public void stateChange(StateChangeEvent event) throws RuntimeException - { - ReplicatedEnvironment.State state = event.getState(); - if (state == ReplicatedEnvironment.State.REPLICA) - { - replicaStateLatch.countDown(); - } - if (state == ReplicatedEnvironment.State.MASTER) - { - masterStateLatch.countDown(); - } - } - }; - String thirdNodeName = TEST_NODE_NAME + "_2"; - ReplicatedEnvironmentFacade thirdNode = addNode(thirdNodeName, node2NodeHostPort, TEST_DESIGNATED_PRIMARY, - testStateChangeListener, new NoopReplicationGroupListener()); - assertTrue("Environment did not become a replica", replicaStateLatch.await(10, TimeUnit.SECONDS)); - assertEquals(3, thirdNode.getNumberOfElectableGroupMembers()); - - firstNode.transferMasterAsynchronously(thirdNodeName); - assertTrue("Environment did not become a master", masterStateLatch.await(10, TimeUnit.SECONDS)); - assertTrue("First node environment did not become a replica", firstNodeReplicaStateLatch.await(10, TimeUnit.SECONDS)); - assertEquals("Unexpected state", ReplicatedEnvironment.State.REPLICA.name(), firstNode.getNodeState()); - } - - public void testBeginTransaction() throws Exception - { - ReplicatedEnvironmentFacade facade = createMaster(); - Transaction txn = null; - try - { - txn = facade.beginTransaction(); - assertNotNull("Transaction is not created", txn); - txn.commit(); - txn = null; - } - finally - { - if (txn != null) - { - txn.abort(); - } - } - } - - public void testSetPermittedNodes() throws Exception - { - ReplicatedEnvironmentFacade firstNode = createMaster(); - - Set<String> permittedNodes = new HashSet<String>(); - permittedNodes.add("localhost:" + TEST_NODE_PORT); - permittedNodes.add("localhost:" + _portHelper.getNextAvailable()); - firstNode.setPermittedNodes(permittedNodes); - - ReplicatedEnvironmentFacade.ReplicationNodeImpl replicationNode = new ReplicatedEnvironmentFacade.ReplicationNodeImpl(TEST_NODE_NAME, TEST_NODE_HOST_PORT); - NodeState nodeState = ReplicatedEnvironmentFacade.getRemoteNodeState(TEST_GROUP_NAME, replicationNode, 5000); - - ObjectMapper objectMapper = new ObjectMapper(); - - Map<String, Object> settings = objectMapper.readValue(nodeState.getAppState(), Map.class); - Collection<String> appStatePermittedNodes = (Collection<String>)settings.get(ReplicatedEnvironmentFacade.PERMITTED_NODE_LIST); - assertEquals("Unexpected permitted nodes", permittedNodes, new HashSet<String>(appStatePermittedNodes)); - } - - public void testPermittedNodeIsAllowedToConnect() throws Exception - { - ReplicatedEnvironmentFacade firstNode = createMaster(); - - int replica1Port = _portHelper.getNextAvailable(); - String node1NodeHostPort = "localhost:" + replica1Port; - - Set<String> permittedNodes = new HashSet<String>(); - permittedNodes.add("localhost:" + TEST_NODE_PORT); - permittedNodes.add(node1NodeHostPort); - firstNode.setPermittedNodes(permittedNodes); - - ReplicatedEnvironmentConfiguration configuration = createReplicatedEnvironmentConfiguration(TEST_NODE_NAME + "_1", node1NodeHostPort, false); - when(configuration.getHelperNodeName()).thenReturn(TEST_NODE_NAME); - - TestStateChangeListener stateChangeListener = new TestStateChangeListener(State.REPLICA); - ReplicatedEnvironmentFacade secondNode = createReplicatedEnvironmentFacade(TEST_NODE_NAME + "_1", - stateChangeListener, new NoopReplicationGroupListener(), configuration); - assertTrue("Environment was not created", stateChangeListener.awaitForStateChange(LISTENER_TIMEOUT, TimeUnit.SECONDS)); - assertEquals("Unexpected state", State.REPLICA.name(), secondNode.getNodeState()); - } - - public void testIntruderNodeIsDetected() throws Exception - { - final CountDownLatch intruderLatch = new CountDownLatch(1); - ReplicationGroupListener listener = new NoopReplicationGroupListener() - { - @Override - public boolean onIntruderNode(ReplicationNode node) - { - intruderLatch.countDown(); - return true; - } - }; - ReplicatedEnvironmentFacade firstNode = createMaster(listener); - int replica1Port = _portHelper.getNextAvailable(); - String node1NodeHostPort = "localhost:" + replica1Port; - - Set<String> permittedNodes = new HashSet<String>(); - permittedNodes.add("localhost:" + TEST_NODE_PORT); - - firstNode.setPermittedNodes(permittedNodes); - - String nodeName = TEST_NODE_NAME + "_1"; - createIntruder(nodeName, node1NodeHostPort); - assertTrue("Intruder node was not detected", intruderLatch.await(10, TimeUnit.SECONDS)); - } - - public void testNodeRolledback() throws Exception - { - DatabaseConfig createConfig = new DatabaseConfig(); - createConfig.setAllowCreate(true); - createConfig.setTransactional(true); - - ReplicatedEnvironmentFacade node1 = createMaster(); - - String replicaNodeHostPort = "localhost:" + _portHelper.getNextAvailable(); - - String replicaName = TEST_NODE_NAME + 1; - ReplicatedEnvironmentFacade node2 = createReplica(replicaName, replicaNodeHostPort, new NoopReplicationGroupListener()); - - node1.setDesignatedPrimary(true); - - Transaction txn = node1.beginTransaction(); - Database db = node1.getEnvironment().openDatabase(txn, "mydb", createConfig); - txn.commit(); - - // Put a record (that will be replicated) - putRecord(node1, db, 1, "value1"); - - node2.close(); - - // Put a record (that will be only on node1 as node2 is now offline) - putRecord(node1, db, 2, "value2"); - - db.close(); - - // Stop node1 - node1.close(); - - // Restart the node2, making it primary so it becomes master - TestStateChangeListener node2StateChangeListener = new TestStateChangeListener(State.MASTER); - node2 = addNode(replicaName, replicaNodeHostPort, true, node2StateChangeListener, new NoopReplicationGroupListener()); - boolean awaitForStateChange = node2StateChangeListener.awaitForStateChange(LISTENER_TIMEOUT, TimeUnit.SECONDS); - assertTrue(replicaName + " did not go into desired state; current actual state is " - + node2StateChangeListener.getCurrentActualState(), awaitForStateChange); - - txn = node2.beginTransaction(); - db = node2.getEnvironment().openDatabase(txn, "mydb", DatabaseConfig.DEFAULT); - txn.commit(); - - // Do a transaction on node2. The two environments will have diverged - putRecord(node2, db, 3, "diverged"); - - // Now restart node1 and ensure that it realises it needs to rollback before it can rejoin. - TestStateChangeListener node1StateChangeListener = new TestStateChangeListener(State.REPLICA); - final CountDownLatch _replicaRolledback = new CountDownLatch(1); - node1 = addNode(node1StateChangeListener, new NoopReplicationGroupListener() - { - @Override - public void onNodeRolledback() - { - _replicaRolledback.countDown(); - } - }); - assertTrue("Node 1 did not go into desired state and remained in state " + node1.getNodeState(), - node1StateChangeListener.awaitForStateChange(LISTENER_TIMEOUT, TimeUnit.SECONDS)); - assertTrue("Node 1 did not experience rollback within timeout", - _replicaRolledback.await(LISTENER_TIMEOUT, TimeUnit.SECONDS)); - - // Finally do one more transaction through the master - putRecord(node2, db, 4, "value4"); - db.close(); - - node1.close(); - node2.close(); - } - - public void testReplicaTransactionBeginsImmediately() throws Exception - { - ReplicatedEnvironmentFacade master = createMaster(); - String nodeName2 = TEST_NODE_NAME + "_2"; - String host = "localhost"; - int port = _portHelper.getNextAvailable(); - String node2NodeHostPort = host + ":" + port; - - final ReplicatedEnvironmentFacade replica = createReplica(nodeName2, node2NodeHostPort, new NoopReplicationGroupListener() ); - - // close the master - master.close(); - - // try to create a transaction in a separate thread - // and make sure that transaction is created immediately. - ExecutorService service = Executors.newSingleThreadExecutor(); - try - { - - Future<Transaction> future = service.submit(new Callable<Transaction>(){ - - @Override - public Transaction call() throws Exception - { - return replica.getEnvironment().beginTransaction(null, null); - } - }); - Transaction transaction = future.get(5, TimeUnit.SECONDS); - assertNotNull("Transaction was not created during expected time", transaction); - transaction.abort(); - } - finally - { - service.shutdown(); - } - } - - public void testReplicaWriteExceptionIsConvertedIntoConnectionScopedRuntimeException() throws Exception - { - ReplicatedEnvironmentFacade master = createMaster(); - String nodeName2 = TEST_NODE_NAME + "_2"; - String host = "localhost"; - int port = _portHelper.getNextAvailable(); - String node2NodeHostPort = host + ":" + port; - - final ReplicatedEnvironmentFacade replica = createReplica(nodeName2, node2NodeHostPort, new NoopReplicationGroupListener() ); - - // close the master - master.close(); - - try - { - replica.openDatabase("test", DatabaseConfig.DEFAULT.setAllowCreate(true) ); - fail("Replica write operation should fail"); - } - catch(ReplicaWriteException e) - { - RuntimeException handledException = master.handleDatabaseException("test", e); - assertTrue("Unexpected exception", handledException instanceof ConnectionScopedRuntimeException); - } - } - - private void putRecord(final ReplicatedEnvironmentFacade master, final Database db, final int keyValue, - final String dataValue) - { - DatabaseEntry key = new DatabaseEntry(); - DatabaseEntry data = new DatabaseEntry(); - - Transaction txn = master.beginTransaction(); - IntegerBinding.intToEntry(keyValue, key); - StringBinding.stringToEntry(dataValue, data); - - db.put(txn, key, data); - txn.commit(); - } - - - private void createIntruder(String nodeName, String node1NodeHostPort) - { - File environmentPathFile = new File(_storePath, nodeName); - environmentPathFile.mkdirs(); - - ReplicationConfig replicationConfig = new ReplicationConfig(TEST_GROUP_NAME, nodeName, node1NodeHostPort); - replicationConfig.setHelperHosts(TEST_NODE_HOST_PORT); - - EnvironmentConfig envConfig = new EnvironmentConfig(); - envConfig.setAllowCreate(true); - envConfig.setTransactional(true); - envConfig.setDurability(TEST_DURABILITY); - ReplicatedEnvironment intruder = null; - try - { - intruder = new ReplicatedEnvironment(environmentPathFile, replicationConfig, envConfig); - } - finally - { - if (intruder != null) - { - intruder.close(); - } - } - } - - private ReplicatedEnvironmentFacade createMaster() throws Exception - { - return createMaster(new NoopReplicationGroupListener()); - } - - private ReplicatedEnvironmentFacade createMaster(ReplicationGroupListener replicationGroupListener) throws Exception - { - TestStateChangeListener stateChangeListener = new TestStateChangeListener(State.MASTER); - ReplicatedEnvironmentFacade env = addNode(stateChangeListener, replicationGroupListener); - assertTrue("Environment was not created", stateChangeListener.awaitForStateChange(LISTENER_TIMEOUT, TimeUnit.SECONDS)); - return env; - } - - private ReplicatedEnvironmentFacade createReplica(String nodeName, String nodeHostPort, ReplicationGroupListener replicationGroupListener) throws Exception - { - TestStateChangeListener testStateChangeListener = new TestStateChangeListener(State.REPLICA); - return createReplica(nodeName, nodeHostPort, testStateChangeListener, replicationGroupListener); - } - - private ReplicatedEnvironmentFacade createReplica(String nodeName, String nodeHostPort, - TestStateChangeListener testStateChangeListener, ReplicationGroupListener replicationGroupListener) - throws InterruptedException - { - ReplicatedEnvironmentFacade replicaEnvironmentFacade = addNode(nodeName, nodeHostPort, TEST_DESIGNATED_PRIMARY, - testStateChangeListener, replicationGroupListener); - 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, - StateChangeListener stateChangeListener, ReplicationGroupListener replicationGroupListener) - { - ReplicatedEnvironmentConfiguration config = createReplicatedEnvironmentConfiguration(nodeName, nodeHostPort, designatedPrimary); - return createReplicatedEnvironmentFacade(nodeName, stateChangeListener, replicationGroupListener, config); - } - - private ReplicatedEnvironmentFacade createReplicatedEnvironmentFacade(String nodeName, StateChangeListener stateChangeListener, ReplicationGroupListener replicationGroupListener, ReplicatedEnvironmentConfiguration config) { - ReplicatedEnvironmentFacade ref = new ReplicatedEnvironmentFacade(config); - ref.setStateChangeListener(stateChangeListener); - ref.setReplicationGroupListener(replicationGroupListener); - ref.setMessageStoreDurability(TEST_DURABILITY.getLocalSync(), TEST_DURABILITY.getReplicaSync(), TEST_DURABILITY.getReplicaAck()); - _nodes.put(nodeName, ref); - return ref; - } - - private ReplicatedEnvironmentFacade addNode(StateChangeListener stateChangeListener, - ReplicationGroupListener replicationGroupListener) - { - return addNode(TEST_NODE_NAME, TEST_NODE_HOST_PORT, TEST_DESIGNATED_PRIMARY, - stateChangeListener, replicationGroupListener); - } - - 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.getHelperNodeName()).thenReturn(TEST_NODE_NAME); - - when(node.getFacadeParameter(eq(ReplicatedEnvironmentFacade.MASTER_TRANSFER_TIMEOUT_PROPERTY_NAME), anyInt())).thenReturn(60000); - when(node.getFacadeParameter(eq(ReplicatedEnvironmentFacade.DB_PING_SOCKET_TIMEOUT_PROPERTY_NAME), anyInt())).thenReturn(10000); - when(node.getFacadeParameter(eq(ReplicatedEnvironmentFacade.REMOTE_NODE_MONITOR_INTERVAL_PROPERTY_NAME), anyInt())).thenReturn(1000); - when(node.getFacadeParameter(eq(ReplicatedEnvironmentFacade.ENVIRONMENT_RESTART_RETRY_LIMIT_PROPERTY_NAME), anyInt())).thenReturn(3); - when(node.getFacadeParameter(eq(ReplicatedEnvironmentFacade.EXECUTOR_SHUTDOWN_TIMEOUT_PROPERTY_NAME), anyInt())).thenReturn(10000); - - 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; - } - - class NoopReplicationGroupListener implements ReplicationGroupListener - { - - @Override - public void onReplicationNodeAddedToGroup(ReplicationNode node) - { - } - - @Override - public void onReplicationNodeRecovered(ReplicationNode node) - { - } - - @Override - public void onReplicationNodeRemovedFromGroup(ReplicationNode node) - { - } - - @Override - public void onNodeState(ReplicationNode node, NodeState nodeState) - { - } - - @Override - public boolean onIntruderNode(ReplicationNode node) - { - LOGGER.warn("Intruder node " + node); - return true; - } - - @Override - public void onNoMajority() - { - } - - @Override - public void onNodeRolledback() - { - } - - @Override - public void onException(Exception e) - { - } - - } -} 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 deleted file mode 100644 index 0870191b35..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/TestStateChangeListener.java +++ /dev/null @@ -1,70 +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.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/tuple/ConfiguredObjectBindingTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBindingTest.java deleted file mode 100644 index 965cad1cb5..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBindingTest.java +++ /dev/null @@ -1,67 +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.tuple; - -import java.util.Collections; -import java.util.Map; -import junit.framework.TestCase; - -import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.store.ConfiguredObjectRecord; - -import com.sleepycat.bind.tuple.TupleInput; -import com.sleepycat.bind.tuple.TupleOutput; -import org.apache.qpid.server.store.ConfiguredObjectRecordImpl; - -public class ConfiguredObjectBindingTest extends TestCase -{ - - private ConfiguredObjectRecord _object; - - private static final Map<String, Object> DUMMY_ATTRIBUTES_MAP = - Collections.singletonMap("dummy",(Object) "attributes"); - - private static final String DUMMY_TYPE_STRING = "dummyType"; - private ConfiguredObjectBinding _configuredObjectBinding; - - @Override - protected void setUp() throws Exception - { - super.setUp(); - _configuredObjectBinding = ConfiguredObjectBinding.getInstance(); - _object = new ConfiguredObjectRecordImpl(UUIDGenerator.generateRandomUUID(), DUMMY_TYPE_STRING, - DUMMY_ATTRIBUTES_MAP); - } - - public void testObjectToEntryAndEntryToObject() - { - TupleOutput tupleOutput = new TupleOutput(); - - _configuredObjectBinding.objectToEntry(_object, tupleOutput); - - byte[] entryAsBytes = tupleOutput.getBufferBytes(); - TupleInput tupleInput = new TupleInput(entryAsBytes); - - ConfiguredObjectRecord storedObject = _configuredObjectBinding.entryToObject(tupleInput); - assertEquals("Unexpected attributes", DUMMY_ATTRIBUTES_MAP, storedObject.getAttributes()); - assertEquals("Unexpected type", DUMMY_TYPE_STRING, storedObject.getType()); - } -} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java deleted file mode 100644 index ce143aba1b..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java +++ /dev/null @@ -1,181 +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.upgrade; - -import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.NONEXCLUSIVE_WITH_ERRONEOUS_OWNER; -import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.NON_DURABLE_QUEUE_NAME; -import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.PRIORITY_QUEUE_NAME; -import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.QUEUE_NAME; -import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.QUEUE_WITH_DLQ_NAME; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.io.File; -import java.io.InputStream; -import java.util.UUID; - -import org.apache.qpid.server.logging.LogSubject; -import org.apache.qpid.server.logging.subjects.TestBlankSubject; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.test.utils.QpidTestCase; -import org.apache.qpid.util.FileUtils; - -import com.sleepycat.je.Database; -import com.sleepycat.je.Environment; -import com.sleepycat.je.EnvironmentConfig; -import com.sleepycat.je.Transaction; - -public abstract class AbstractUpgradeTestCase extends QpidTestCase -{ - protected static final class StaticAnswerHandler implements UpgradeInteractionHandler - { - private UpgradeInteractionResponse _response; - - public StaticAnswerHandler(UpgradeInteractionResponse response) - { - _response = response; - } - - @Override - public UpgradeInteractionResponse requireResponse(String question, UpgradeInteractionResponse defaultResponse, - UpgradeInteractionResponse... possibleResponses) - { - return _response; - } - } - - public static final String[] QUEUE_NAMES = { "clientid:myDurSubName", "clientid:mySelectorDurSubName", QUEUE_NAME, NON_DURABLE_QUEUE_NAME, - NONEXCLUSIVE_WITH_ERRONEOUS_OWNER, PRIORITY_QUEUE_NAME, QUEUE_WITH_DLQ_NAME, QUEUE_WITH_DLQ_NAME + "_DLQ" }; - public static int[] QUEUE_SIZES = { 1, 1, 10, 3, 0, 0, 0, 1}; - public static int TOTAL_MESSAGE_NUMBER = 16; - protected static final LogSubject LOG_SUBJECT = new TestBlankSubject(); - - // myQueueWithDLQ_DLQ is not bound to the default exchange - protected static final int TOTAL_BINDINGS = QUEUE_NAMES.length * 2 - 1; - protected static final int TOTAL_EXCHANGES = 6; - - private File _storeLocation; - protected Environment _environment; - - @Override - public void setUp() throws Exception - { - super.setUp(); - _storeLocation = copyStore(getStoreDirectoryName()); - - _environment = createEnvironment(_storeLocation); - } - - /** @return eg "bdbstore-v4" - used for copying store */ - protected abstract String getStoreDirectoryName(); - - protected Environment createEnvironment(File storeLocation) - { - EnvironmentConfig envConfig = new EnvironmentConfig(); - envConfig.setAllowCreate(true); - envConfig.setTransactional(true); - envConfig.setConfigParam("je.lock.nLockTables", "7"); - envConfig.setReadOnly(false); - envConfig.setSharedCache(false); - envConfig.setCacheSize(0); - return new Environment(storeLocation, envConfig); - } - - @Override - public void tearDown() throws Exception - { - try - { - _environment.close(); - } - finally - { - _environment = null; - deleteDirectoryIfExists(_storeLocation); - } - super.tearDown(); - } - - private File copyStore(String storeDirectoryName) throws Exception - { - File storeLocation = new File(new File(TMP_FOLDER), "test-store"); - deleteDirectoryIfExists(storeLocation); - storeLocation.mkdirs(); - int index = 0; - String prefix = "0000000"; - String extension = ".jdb"; - InputStream is = null; - do - { - String fileName = prefix + index + extension; - is = getClass().getClassLoader().getResourceAsStream("upgrade/" + storeDirectoryName + "/test-store/" + fileName); - if (is != null) - { - FileUtils.copy(is, new File(storeLocation, fileName)); - } - index++; - } - while (is != null); - return storeLocation; - } - - protected void deleteDirectoryIfExists(File dir) - { - if (dir.exists()) - { - assertTrue("The provided file " + dir + " is not a directory", dir.isDirectory()); - - boolean deletedSuccessfully = FileUtils.delete(dir, true); - - assertTrue("Files at '" + dir + "' should have been deleted", deletedSuccessfully); - } - } - - protected void assertDatabaseRecordCount(String databaseName, final long expectedCountNumber) - { - long count = getDatabaseCount(databaseName); - assertEquals("Unexpected database '" + databaseName + "' entry number", expectedCountNumber, count); - } - - protected long getDatabaseCount(String databaseName) - { - DatabaseCallable<Long> operation = new DatabaseCallable<Long>() - { - - @Override - public Long call(Database sourceDatabase, Database targetDatabase, Transaction transaction) - { - return new Long(sourceDatabase.count()); - - } - }; - Long count = new DatabaseTemplate(_environment, databaseName, null).call(operation); - return count.longValue(); - } - - public VirtualHost getVirtualHost() - { - VirtualHost virtualHost = mock(VirtualHost.class); - when(virtualHost.getName()).thenReturn(getName()); - when(virtualHost.getId()).thenReturn(UUID.randomUUID()); - return virtualHost; - } -} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/DatabaseTemplateTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/DatabaseTemplateTest.java deleted file mode 100644 index 7ec442b73d..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/DatabaseTemplateTest.java +++ /dev/null @@ -1,83 +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.upgrade; - -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.isA; -import static org.mockito.Matchers.same; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import junit.framework.TestCase; - -import com.sleepycat.je.Database; -import com.sleepycat.je.DatabaseConfig; -import com.sleepycat.je.Environment; -import com.sleepycat.je.Transaction; - -public class DatabaseTemplateTest extends TestCase -{ - private static final String SOURCE_DATABASE = "sourceDatabase"; - private Environment _environment; - private Database _sourceDatabase; - - @Override - public void setUp() throws Exception - { - super.setUp(); - _environment = mock(Environment.class); - _sourceDatabase = mock(Database.class); - when(_environment.openDatabase(any(Transaction.class), same(SOURCE_DATABASE), isA(DatabaseConfig.class))) - .thenReturn(_sourceDatabase); - } - - public void testExecuteWithTwoDatabases() - { - String targetDatabaseName = "targetDatabase"; - Database targetDatabase = mock(Database.class); - - Transaction txn = mock(Transaction.class); - - when(_environment.openDatabase(same(txn), same(targetDatabaseName), isA(DatabaseConfig.class))) - .thenReturn(targetDatabase); - - DatabaseTemplate databaseTemplate = new DatabaseTemplate(_environment, SOURCE_DATABASE, targetDatabaseName, txn); - - DatabaseRunnable databaseOperation = mock(DatabaseRunnable.class); - databaseTemplate.run(databaseOperation); - - verify(databaseOperation).run(_sourceDatabase, targetDatabase, txn); - verify(_sourceDatabase).close(); - verify(targetDatabase).close(); - } - - public void testExecuteWithOneDatabases() - { - DatabaseTemplate databaseTemplate = new DatabaseTemplate(_environment, SOURCE_DATABASE, null, null); - - DatabaseRunnable databaseOperation = mock(DatabaseRunnable.class); - databaseTemplate.run(databaseOperation); - - verify(databaseOperation).run(_sourceDatabase, (Database)null, (Transaction)null); - verify(_sourceDatabase).close(); - } - -} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java deleted file mode 100644 index d0f9455d9a..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.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.store.berkeleydb.upgrade; - -import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.NONEXCLUSIVE_WITH_ERRONEOUS_OWNER; -import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.NON_DURABLE_QUEUE_NAME; -import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.QUEUE_NAME; -import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.QUEUE_WITH_DLQ_NAME; -import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.SELECTOR_TOPIC_NAME; -import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.TOPIC_NAME; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -import org.apache.qpid.common.AMQPFilterTypes; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom4To5.BindingRecord; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom4To5.BindingTuple; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom4To5.MessageContentKey; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom4To5.MessageContentKeyBinding; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom4To5.QueueEntryKey; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom4To5.QueueEntryKeyBinding; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom4To5.QueueRecord; - -import com.sleepycat.bind.tuple.LongBinding; -import com.sleepycat.je.Database; -import com.sleepycat.je.DatabaseEntry; -import com.sleepycat.je.Transaction; - -public class UpgradeFrom4to5Test extends AbstractUpgradeTestCase -{ - private static final String DURABLE_SUBSCRIPTION_QUEUE_WITH_SELECTOR = "clientid:mySelectorDurSubName"; - private static final String DURABLE_SUBSCRIPTION_QUEUE = "clientid:myDurSubName"; - private static final String EXCHANGE_DB_NAME = "exchangeDb_v5"; - private static final String MESSAGE_META_DATA_DB_NAME = "messageMetaDataDb_v5"; - private static final String MESSAGE_CONTENT_DB_NAME = "messageContentDb_v5"; - private static final String DELIVERY_DB_NAME = "deliveryDb_v5"; - private static final String BINDING_DB_NAME = "queueBindingsDb_v5"; - - @Override - protected String getStoreDirectoryName() - { - return "bdbstore-v4"; - } - - public void testPerformUpgradeWithHandlerAnsweringYes() throws Exception - { - UpgradeFrom4To5 upgrade = new UpgradeFrom4To5(); - upgrade.performUpgrade(_environment, new StaticAnswerHandler(UpgradeInteractionResponse.YES), getVirtualHost()); - - assertQueues(new HashSet<String>(Arrays.asList(QUEUE_NAMES))); - - assertDatabaseRecordCount(DELIVERY_DB_NAME, TOTAL_MESSAGE_NUMBER); - assertDatabaseRecordCount(MESSAGE_META_DATA_DB_NAME, TOTAL_MESSAGE_NUMBER); - assertDatabaseRecordCount(EXCHANGE_DB_NAME, TOTAL_EXCHANGES); - - for (int i = 0; i < QUEUE_SIZES.length; i++) - { - assertQueueMessages(QUEUE_NAMES[i], QUEUE_SIZES[i]); - } - - final List<BindingRecord> queueBindings = loadBindings(); - - assertEquals("Unxpected bindings size", TOTAL_BINDINGS, queueBindings.size()); - assertBindingRecord(queueBindings, DURABLE_SUBSCRIPTION_QUEUE, "amq.topic", TOPIC_NAME, ""); - assertBindingRecord(queueBindings, DURABLE_SUBSCRIPTION_QUEUE_WITH_SELECTOR, "amq.topic", SELECTOR_TOPIC_NAME, "testprop='true'"); - assertBindingRecord(queueBindings, QUEUE_NAME, "amq.direct", QUEUE_NAME, null); - assertBindingRecord(queueBindings, NON_DURABLE_QUEUE_NAME, "amq.direct", NON_DURABLE_QUEUE_NAME, null); - assertBindingRecord(queueBindings, NONEXCLUSIVE_WITH_ERRONEOUS_OWNER, "amq.direct", NONEXCLUSIVE_WITH_ERRONEOUS_OWNER, null); - - assertQueueHasOwner(NONEXCLUSIVE_WITH_ERRONEOUS_OWNER, "misused-owner-as-description"); - - assertContent(); - } - - public void testPerformUpgradeWithHandlerAnsweringNo() throws Exception - { - UpgradeFrom4To5 upgrade = new UpgradeFrom4To5(); - upgrade.performUpgrade(_environment, new StaticAnswerHandler(UpgradeInteractionResponse.NO), getVirtualHost()); - HashSet<String> queues = new HashSet<String>(Arrays.asList(QUEUE_NAMES)); - assertTrue(NON_DURABLE_QUEUE_NAME + " should be in the list of queues" , queues.remove(NON_DURABLE_QUEUE_NAME)); - - assertQueues(queues); - - assertDatabaseRecordCount(DELIVERY_DB_NAME, 13); - assertDatabaseRecordCount(MESSAGE_META_DATA_DB_NAME, 13); - assertDatabaseRecordCount(EXCHANGE_DB_NAME, TOTAL_EXCHANGES); - - assertQueueMessages(DURABLE_SUBSCRIPTION_QUEUE, 1); - assertQueueMessages(DURABLE_SUBSCRIPTION_QUEUE_WITH_SELECTOR, 1); - assertQueueMessages(QUEUE_NAME, 10); - assertQueueMessages(QUEUE_WITH_DLQ_NAME + "_DLQ", 1); - - final List<BindingRecord> queueBindings = loadBindings(); - - assertEquals("Unxpected list size", TOTAL_BINDINGS - 2, queueBindings.size()); - assertBindingRecord(queueBindings, DURABLE_SUBSCRIPTION_QUEUE, "amq.topic", TOPIC_NAME, ""); - assertBindingRecord(queueBindings, DURABLE_SUBSCRIPTION_QUEUE_WITH_SELECTOR, "amq.topic", - SELECTOR_TOPIC_NAME, "testprop='true'"); - assertBindingRecord(queueBindings, QUEUE_NAME, "amq.direct", QUEUE_NAME, null); - - assertQueueHasOwner(NONEXCLUSIVE_WITH_ERRONEOUS_OWNER, "misused-owner-as-description"); - - assertContent(); - } - - private List<BindingRecord> loadBindings() - { - final BindingTuple bindingTuple = new BindingTuple(); - final List<BindingRecord> queueBindings = new ArrayList<BindingRecord>(); - CursorOperation databaseOperation = new CursorOperation() - { - - @Override - public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, - DatabaseEntry key, DatabaseEntry value) - { - BindingRecord bindingRecord = bindingTuple.entryToObject(key); - - AMQShortString queueName = bindingRecord.getQueueName(); - AMQShortString exchangeName = bindingRecord.getExchangeName(); - AMQShortString routingKey = bindingRecord.getRoutingKey(); - FieldTable arguments = bindingRecord.getArguments(); - queueBindings.add(new BindingRecord(exchangeName, queueName, routingKey, arguments)); - } - }; - new DatabaseTemplate(_environment, BINDING_DB_NAME, null).run(databaseOperation); - return queueBindings; - } - - private void assertBindingRecord(List<BindingRecord> queueBindings, String queueName, String exchangeName, - String routingKey, String selectorKey) - { - BindingRecord record = null; - for (BindingRecord bindingRecord : queueBindings) - { - if (bindingRecord.getQueueName().asString().equals(queueName) - && bindingRecord.getExchangeName().asString().equals(exchangeName)) - { - record = bindingRecord; - break; - } - } - assertNotNull("Binding is not found for queue " + queueName + " and exchange " + exchangeName, record); - assertEquals("Unexpected routing key", routingKey, record.getRoutingKey().asString()); - - if (selectorKey != null) - { - assertEquals("Unexpected selector key for " + queueName, selectorKey, - record.getArguments().get(AMQPFilterTypes.JMS_SELECTOR.getValue())); - } - } - - private void assertQueueMessages(final String queueName, final int expectedQueueSize) - { - final Set<Long> messageIdsForQueue = assertDeliveriesForQueue(queueName, expectedQueueSize); - - assertMetadataForQueue(queueName, expectedQueueSize, messageIdsForQueue); - - assertContentForQueue(queueName, expectedQueueSize, messageIdsForQueue); - } - - private Set<Long> assertDeliveriesForQueue(final String queueName, final int expectedQueueSize) - { - final QueueEntryKeyBinding queueEntryKeyBinding = new QueueEntryKeyBinding(); - final AtomicInteger deliveryCounter = new AtomicInteger(); - final Set<Long> messagesForQueue = new HashSet<Long>(); - - CursorOperation deliveryDatabaseOperation = new CursorOperation() - { - @Override - public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, - DatabaseEntry key, DatabaseEntry value) - { - QueueEntryKey entryKey = queueEntryKeyBinding.entryToObject(key); - String thisQueueName = entryKey.getQueueName().asString(); - if (thisQueueName.equals(queueName)) - { - deliveryCounter.incrementAndGet(); - messagesForQueue.add(entryKey.getMessageId()); - } - } - }; - new DatabaseTemplate(_environment, DELIVERY_DB_NAME, null).run(deliveryDatabaseOperation); - - assertEquals("Unxpected number of entries in delivery db for queue " + queueName, expectedQueueSize, - deliveryCounter.get()); - - return messagesForQueue; - } - - private void assertMetadataForQueue(final String queueName, final int expectedQueueSize, - final Set<Long> messageIdsForQueue) - { - final AtomicInteger metadataCounter = new AtomicInteger(); - CursorOperation databaseOperation = new CursorOperation() - { - - @Override - public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, - DatabaseEntry key, DatabaseEntry value) - { - Long messageId = LongBinding.entryToLong(key); - - boolean messageIsForTheRightQueue = messageIdsForQueue.contains(messageId); - if (messageIsForTheRightQueue) - { - metadataCounter.incrementAndGet(); - } - } - }; - new DatabaseTemplate(_environment, MESSAGE_META_DATA_DB_NAME, null).run(databaseOperation); - - assertEquals("Unxpected number of entries in metadata db for queue " + queueName, expectedQueueSize, - metadataCounter.get()); - } - - private void assertContentForQueue(String queueName, int expectedQueueSize, final Set<Long> messageIdsForQueue) - { - final AtomicInteger contentCounter = new AtomicInteger(); - final MessageContentKeyBinding keyBinding = new MessageContentKeyBinding(); - CursorOperation cursorOperation = new CursorOperation() - { - private long _prevMsgId = -1; - - @Override - public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, - DatabaseEntry key, DatabaseEntry value) - { - MessageContentKey contentKey = keyBinding.entryToObject(key); - long msgId = contentKey.getMessageId(); - - if (_prevMsgId != msgId && messageIdsForQueue.contains(msgId)) - { - contentCounter.incrementAndGet(); - } - - _prevMsgId = msgId; - } - }; - new DatabaseTemplate(_environment, MESSAGE_CONTENT_DB_NAME, null).run(cursorOperation); - - assertEquals("Unxpected number of entries in content db for queue " + queueName, expectedQueueSize, - contentCounter.get()); - } - - private void assertQueues(Set<String> expectedQueueNames) - { - List<AMQShortString> durableSubNames = Collections.emptyList(); - final UpgradeFrom4To5.QueueRecordBinding binding = new UpgradeFrom4To5.QueueRecordBinding(durableSubNames); - final Set<String> actualQueueNames = new HashSet<String>(); - - CursorOperation queueNameCollector = new CursorOperation() - { - - @Override - public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, - DatabaseEntry key, DatabaseEntry value) - { - QueueRecord record = binding.entryToObject(value); - String queueName = record.getNameShortString().asString(); - actualQueueNames.add(queueName); - } - }; - new DatabaseTemplate(_environment, "queueDb_v5", null).run(queueNameCollector); - - assertEquals("Unexpected queue names", expectedQueueNames, actualQueueNames); - } - - private void assertQueueHasOwner(String queueName, final String expectedOwner) - { - List<AMQShortString> durableSubNames = Collections.emptyList(); - final UpgradeFrom4To5.QueueRecordBinding binding = new UpgradeFrom4To5.QueueRecordBinding(durableSubNames); - final AtomicReference<String> actualOwner = new AtomicReference<String>(); - final AtomicBoolean foundQueue = new AtomicBoolean(false); - - CursorOperation queueNameCollector = new CursorOperation() - { - - @Override - public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, - DatabaseEntry key, DatabaseEntry value) - { - QueueRecord record = binding.entryToObject(value); - String queueName = record.getNameShortString().asString(); - if (queueName.equals(queueName)) - { - foundQueue.set(true); - actualOwner.set(AMQShortString.toString(record.getOwner())); - } - } - }; - new DatabaseTemplate(_environment, "queueDb_v5", null).run(queueNameCollector); - - assertTrue("Could not find queue in database", foundQueue.get()); - assertEquals("Queue has unexpected owner", expectedOwner, actualOwner.get()); - } - - private void assertContent() - { - final UpgradeFrom4To5.ContentBinding contentBinding = new UpgradeFrom4To5.ContentBinding(); - CursorOperation contentCursorOperation = new CursorOperation() - { - - @Override - public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, DatabaseEntry key, - DatabaseEntry value) - { - long id = LongBinding.entryToLong(key); - assertTrue("Unexpected id", id > 0); - ByteBuffer content = contentBinding.entryToObject(value); - assertNotNull("Unexpected content", content); - } - }; - new DatabaseTemplate(_environment, MESSAGE_CONTENT_DB_NAME, null).run(contentCursorOperation); - } -} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java deleted file mode 100644 index 6351ee5205..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java +++ /dev/null @@ -1,445 +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.upgrade; - -import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.PRIORITY_QUEUE_NAME; -import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.QUEUE_WITH_DLQ_NAME; -import static org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.CONFIGURED_OBJECTS_DB_NAME; -import static org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.NEW_CONTENT_DB_NAME; -import static org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.NEW_DELIVERY_DB_NAME; -import static org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.NEW_METADATA_DB_NAME; -import static org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.NEW_XID_DB_NAME; -import static org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.OLD_CONTENT_DB_NAME; -import static org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.OLD_XID_DB_NAME; - -import java.io.File; -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.Map.Entry; -import java.util.Set; -import java.util.UUID; - -import com.sleepycat.bind.tuple.LongBinding; -import com.sleepycat.je.Database; -import com.sleepycat.je.DatabaseEntry; -import com.sleepycat.je.Environment; -import com.sleepycat.je.LockMode; -import com.sleepycat.je.Transaction; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.server.model.Binding; -import org.apache.qpid.server.model.Exchange; -import org.apache.qpid.server.model.LifetimePolicy; -import org.apache.qpid.server.model.Queue; -import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.queue.QueueArgumentsConverter; -import org.apache.qpid.server.store.Xid; -import org.apache.qpid.server.store.berkeleydb.tuple.XidBinding; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.CompoundKey; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.CompoundKeyBinding; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.ConfiguredObjectBinding; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.NewDataBinding; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.NewPreparedTransaction; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.NewPreparedTransactionBinding; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.NewQueueEntryBinding; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.NewQueueEntryKey; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.NewRecordImpl; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.OldPreparedTransaction; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.OldPreparedTransactionBinding; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.OldRecordImpl; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.UpgradeConfiguredObjectRecord; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.UpgradeUUIDBinding; -import org.apache.qpid.server.util.MapJsonSerializer; - -public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase -{ - private static final Logger _logger = LoggerFactory.getLogger(UpgradeFrom5To6Test.class); - private static final String ARGUMENTS = "arguments"; - - @Override - protected String getStoreDirectoryName() - { - return "bdbstore-v5"; - } - - public void testPerformUpgrade() throws Exception - { - UpgradeFrom5To6 upgrade = new UpgradeFrom5To6(); - upgrade.performUpgrade(_environment, UpgradeInteractionHandler.DEFAULT_HANDLER, getVirtualHost()); - - assertDatabaseRecordCounts(); - assertContent(); - - assertConfiguredObjects(); - assertQueueEntries(); - } - - public void testPerformUpgradeWithMissingMessageChunkKeepsIncompleteMessage() throws Exception - { - corruptDatabase(); - - UpgradeFrom5To6 upgrade = new UpgradeFrom5To6(); - upgrade.performUpgrade(_environment, new StaticAnswerHandler(UpgradeInteractionResponse.YES), getVirtualHost()); - - assertDatabaseRecordCounts(); - - assertConfiguredObjects(); - assertQueueEntries(); - } - - public void testPerformUpgradeWithMissingMessageChunkDiscardsIncompleteMessage() throws Exception - { - corruptDatabase(); - - UpgradeFrom5To6 upgrade = new UpgradeFrom5To6(); - - UpgradeInteractionHandler discardMessageInteractionHandler = new StaticAnswerHandler(UpgradeInteractionResponse.NO); - - upgrade.performUpgrade(_environment, discardMessageInteractionHandler, getVirtualHost()); - - assertDatabaseRecordCount(NEW_METADATA_DB_NAME, 12); - assertDatabaseRecordCount(NEW_CONTENT_DB_NAME, 12); - - assertConfiguredObjects(); - assertQueueEntries(); - } - - public void testPerformXidUpgrade() throws Exception - { - File storeLocation = new File(TMP_FOLDER, getName()); - storeLocation.mkdirs(); - Environment environment = createEnvironment(storeLocation); - try - { - populateOldXidEntries(environment); - UpgradeFrom5To6 upgrade = new UpgradeFrom5To6(); - upgrade.performUpgrade(environment, UpgradeInteractionHandler.DEFAULT_HANDLER, getVirtualHost()); - assertXidEntries(environment); - } - finally - { - try - { - environment.close(); - } - finally - { - deleteDirectoryIfExists(storeLocation); - } - - } - } - - private void assertXidEntries(Environment environment) - { - final DatabaseEntry value = new DatabaseEntry(); - final DatabaseEntry key = getXidKey(); - new DatabaseTemplate(environment, NEW_XID_DB_NAME, null).run(new DatabaseRunnable() - { - - @Override - public void run(Database xidDatabase, Database nullDatabase, Transaction transaction) - { - xidDatabase.get(null, key, value, LockMode.DEFAULT); - } - }); - NewPreparedTransactionBinding newBinding = new NewPreparedTransactionBinding(); - NewPreparedTransaction newTransaction = newBinding.entryToObject(value); - NewRecordImpl[] newEnqueues = newTransaction.getEnqueues(); - NewRecordImpl[] newDequeues = newTransaction.getDequeues(); - assertEquals("Unxpected new enqueus number", 1, newEnqueues.length); - NewRecordImpl enqueue = newEnqueues[0]; - assertEquals("Unxpected queue id", UUIDGenerator.generateQueueUUID("TEST1", getVirtualHost().getName()), enqueue.getId()); - assertEquals("Unxpected message id", 1, enqueue.getMessageNumber()); - assertEquals("Unxpected new dequeues number", 1, newDequeues.length); - NewRecordImpl dequeue = newDequeues[0]; - assertEquals("Unxpected queue id", UUIDGenerator.generateQueueUUID("TEST2", getVirtualHost().getName()), dequeue.getId()); - assertEquals("Unxpected message id", 2, dequeue.getMessageNumber()); - } - - private void populateOldXidEntries(Environment environment) - { - - final DatabaseEntry value = new DatabaseEntry(); - OldRecordImpl[] enqueues = { new OldRecordImpl("TEST1", 1) }; - OldRecordImpl[] dequeues = { new OldRecordImpl("TEST2", 2) }; - OldPreparedTransaction oldPreparedTransaction = new OldPreparedTransaction(enqueues, dequeues); - OldPreparedTransactionBinding oldPreparedTransactionBinding = new OldPreparedTransactionBinding(); - oldPreparedTransactionBinding.objectToEntry(oldPreparedTransaction, value); - - final DatabaseEntry key = getXidKey(); - new DatabaseTemplate(environment, OLD_XID_DB_NAME, null).run(new DatabaseRunnable() - { - - @Override - public void run(Database xidDatabase, Database nullDatabase, Transaction transaction) - { - xidDatabase.put(null, key, value); - } - }); - } - - protected DatabaseEntry getXidKey() - { - final DatabaseEntry value = new DatabaseEntry(); - byte[] globalId = { 1 }; - byte[] branchId = { 2 }; - Xid xid = new Xid(1l, globalId, branchId); - XidBinding xidBinding = XidBinding.getInstance(); - xidBinding.objectToEntry(xid, value); - return value; - } - - private void assertQueueEntries() - { - final Map<UUID, UpgradeConfiguredObjectRecord> configuredObjects = loadConfiguredObjects(); - final NewQueueEntryBinding newBinding = new NewQueueEntryBinding(); - CursorOperation cursorOperation = new CursorOperation() - { - - @Override - public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, - DatabaseEntry key, DatabaseEntry value) - { - NewQueueEntryKey newEntryRecord = newBinding.entryToObject(key); - assertTrue("Unexpected queue id", configuredObjects.containsKey(newEntryRecord.getQueueId())); - } - }; - new DatabaseTemplate(_environment, NEW_DELIVERY_DB_NAME, null).run(cursorOperation); - } - - /** - * modify the chunk offset of a message to be wrong, so we can test logic - * that preserves incomplete messages - */ - private void corruptDatabase() - { - CursorOperation cursorOperation = new CursorOperation() - { - - @Override - public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, - DatabaseEntry key, DatabaseEntry value) - { - CompoundKeyBinding binding = new CompoundKeyBinding(); - CompoundKey originalCompoundKey = binding.entryToObject(key); - int corruptedOffset = originalCompoundKey.getOffset() + 2; - CompoundKey corruptedCompoundKey = new CompoundKey(originalCompoundKey.getMessageId(), corruptedOffset); - DatabaseEntry newKey = new DatabaseEntry(); - binding.objectToEntry(corruptedCompoundKey, newKey); - - _logger.info("Deliberately corrupted message id " + originalCompoundKey.getMessageId() - + ", changed offset from " + originalCompoundKey.getOffset() + " to " - + corruptedCompoundKey.getOffset()); - - deleteCurrent(); - sourceDatabase.put(transaction, newKey, value); - - abort(); - } - }; - - Transaction transaction = _environment.beginTransaction(null, null); - new DatabaseTemplate(_environment, OLD_CONTENT_DB_NAME, transaction).run(cursorOperation); - transaction.commit(); - } - - private void assertDatabaseRecordCounts() - { - assertDatabaseRecordCount(CONFIGURED_OBJECTS_DB_NAME, 21); - assertDatabaseRecordCount(NEW_DELIVERY_DB_NAME, 13); - - assertDatabaseRecordCount(NEW_METADATA_DB_NAME, 13); - assertDatabaseRecordCount(NEW_CONTENT_DB_NAME, 13); - } - - private void assertConfiguredObjects() - { - Map<UUID, UpgradeConfiguredObjectRecord> configuredObjects = loadConfiguredObjects(); - assertEquals("Unexpected number of configured objects", 21, configuredObjects.size()); - - Set<Map<String, Object>> expected = new HashSet<Map<String, Object>>(12); - List<UUID> expectedBindingIDs = new ArrayList<UUID>(); - - expected.add(createExpectedQueueMap("myUpgradeQueue", Boolean.FALSE, null, null)); - expected.add(createExpectedQueueMap("clientid:mySelectorDurSubName", Boolean.TRUE, "clientid", null)); - expected.add(createExpectedQueueMap("clientid:myDurSubName", Boolean.TRUE, "clientid", null)); - - final Map<String, Object> queueWithOwnerArguments = new HashMap<String, Object>(); - queueWithOwnerArguments.put(QueueArgumentsConverter.X_QPID_PRIORITIES, 10); - queueWithOwnerArguments.put(QueueArgumentsConverter.X_QPID_DESCRIPTION, "misused-owner-as-description"); - expected.add(createExpectedQueueMap("nonexclusive-with-erroneous-owner", Boolean.FALSE, null,queueWithOwnerArguments)); - - final Map<String, Object> priorityQueueArguments = new HashMap<String, Object>(); - priorityQueueArguments.put(QueueArgumentsConverter.X_QPID_PRIORITIES, 10); - expected.add(createExpectedQueueMap(PRIORITY_QUEUE_NAME, Boolean.FALSE, null, priorityQueueArguments)); - - final Map<String, Object> queueWithDLQArguments = new HashMap<String, Object>(); - queueWithDLQArguments.put("x-qpid-dlq-enabled", true); - queueWithDLQArguments.put("x-qpid-maximum-delivery-count", 2); - expected.add(createExpectedQueueMap(QUEUE_WITH_DLQ_NAME, Boolean.FALSE, null, queueWithDLQArguments)); - - final Map<String, Object> dlqArguments = new HashMap<String, Object>(); - dlqArguments.put("x-qpid-dlq-enabled", false); - dlqArguments.put("x-qpid-maximum-delivery-count", 0); - expected.add(createExpectedQueueMap(QUEUE_WITH_DLQ_NAME + "_DLQ", Boolean.FALSE, null, dlqArguments)); - expected.add(createExpectedExchangeMap(QUEUE_WITH_DLQ_NAME + "_DLE", "fanout")); - - expected.add(createExpectedQueueBindingMapAndID("myUpgradeQueue","myUpgradeQueue", "<<default>>", null, expectedBindingIDs)); - expected.add(createExpectedQueueBindingMapAndID("myUpgradeQueue", "myUpgradeQueue", "amq.direct", null, expectedBindingIDs)); - expected.add(createExpectedQueueBindingMapAndID("clientid:myDurSubName", "myUpgradeTopic", "amq.topic", - Collections.singletonMap("x-filter-jms-selector", ""), expectedBindingIDs)); - expected.add(createExpectedQueueBindingMapAndID("clientid:mySelectorDurSubName", "mySelectorUpgradeTopic", "amq.topic", - Collections.singletonMap("x-filter-jms-selector", "testprop='true'"), expectedBindingIDs)); - expected.add(createExpectedQueueBindingMapAndID("clientid:myDurSubName", "clientid:myDurSubName", "<<default>>", null, expectedBindingIDs)); - expected.add(createExpectedQueueBindingMapAndID("clientid:mySelectorDurSubName", "clientid:mySelectorDurSubName", "<<default>>", null, expectedBindingIDs)); - expected.add(createExpectedQueueBindingMapAndID("nonexclusive-with-erroneous-owner", "nonexclusive-with-erroneous-owner", "amq.direct", null, expectedBindingIDs)); - expected.add(createExpectedQueueBindingMapAndID("nonexclusive-with-erroneous-owner","nonexclusive-with-erroneous-owner", "<<default>>", null, expectedBindingIDs)); - - expected.add(createExpectedQueueBindingMapAndID(PRIORITY_QUEUE_NAME, PRIORITY_QUEUE_NAME, "<<default>>", null, expectedBindingIDs)); - expected.add(createExpectedQueueBindingMapAndID(PRIORITY_QUEUE_NAME, PRIORITY_QUEUE_NAME, "amq.direct", null, expectedBindingIDs)); - - expected.add(createExpectedQueueBindingMapAndID(QUEUE_WITH_DLQ_NAME, QUEUE_WITH_DLQ_NAME, "<<default>>", null, expectedBindingIDs)); - expected.add(createExpectedQueueBindingMapAndID(QUEUE_WITH_DLQ_NAME, QUEUE_WITH_DLQ_NAME, "amq.direct", null, expectedBindingIDs)); - expected.add(createExpectedQueueBindingMapAndID(QUEUE_WITH_DLQ_NAME + "_DLQ", "dlq", QUEUE_WITH_DLQ_NAME + "_DLE", null, expectedBindingIDs)); - - Set<String> expectedTypes = new HashSet<String>(); - expectedTypes.add(Queue.class.getName()); - expectedTypes.add(Exchange.class.getName()); - expectedTypes.add(Binding.class.getName()); - MapJsonSerializer jsonSerializer = new MapJsonSerializer(); - for (Entry<UUID, UpgradeConfiguredObjectRecord> entry : configuredObjects.entrySet()) - { - UpgradeConfiguredObjectRecord object = entry.getValue(); - Map<String, Object> deserialized = jsonSerializer.deserialize(object.getAttributes()); - - assertTrue("Unexpected entry in a store - json [" + object.getAttributes() + "], map [" + deserialized + "]", - expected.remove(deserialized)); - String type = object.getType(); - assertTrue("Unexpected type:" + type, expectedTypes.contains(type)); - UUID key = entry.getKey(); - - assertNotNull("Key cannot be null", key); - - if (type.equals(Exchange.class.getName())) - { - String exchangeName = (String) deserialized.get(Exchange.NAME); - assertNotNull(exchangeName); - assertEquals("Unexpected key", key, UUIDGenerator.generateExchangeUUID(exchangeName, getVirtualHost().getName())); - } - else if (type.equals(Queue.class.getName())) - { - String queueName = (String) deserialized.get(Queue.NAME); - assertNotNull(queueName); - assertEquals("Unexpected key", key, UUIDGenerator.generateQueueUUID(queueName, getVirtualHost().getName())); - } - else if (type.equals(Binding.class.getName())) - { - assertTrue("unexpected binding id", expectedBindingIDs.remove(key)); - } - } - - assertTrue("Not all expected configured objects found:" + expected, expected.isEmpty()); - assertTrue("Not all expected bindings found:" + expectedBindingIDs, expectedBindingIDs.isEmpty()); - } - - private Map<String, Object> createExpectedQueueBindingMapAndID(String queue, String bindingName, String exchangeName, Map<String, String> argumentMap, List<UUID> expectedBindingIDs) - { - Map<String, Object> expectedQueueBinding = new HashMap<String, Object>(); - expectedQueueBinding.put(Binding.QUEUE, UUIDGenerator.generateQueueUUID(queue, getVirtualHost().getName()).toString()); - expectedQueueBinding.put(Binding.NAME, bindingName); - expectedQueueBinding.put(Binding.EXCHANGE, UUIDGenerator.generateExchangeUUID(exchangeName, getVirtualHost().getName()).toString()); - if (argumentMap != null) - { - expectedQueueBinding.put(Binding.ARGUMENTS, argumentMap); - } - - expectedBindingIDs.add(UUIDGenerator.generateBindingUUID(exchangeName, queue, bindingName, getVirtualHost().getName())); - - return expectedQueueBinding; - } - - private Map<String, Object> createExpectedQueueMap(String name, boolean exclusiveFlag, String owner, Map<String, Object> argumentMap) - { - Map<String, Object> expectedQueueEntry = new HashMap<String, Object>(); - expectedQueueEntry.put(Queue.NAME, name); - expectedQueueEntry.put(Queue.EXCLUSIVE, exclusiveFlag); - expectedQueueEntry.put(Queue.OWNER, owner); - if (argumentMap != null) - { - expectedQueueEntry.put(ARGUMENTS, argumentMap); - } - return expectedQueueEntry; - } - - private Map<String, Object> createExpectedExchangeMap(String name, String type) - { - Map<String, Object> expectedExchnageEntry = new HashMap<String, Object>(); - expectedExchnageEntry.put(Exchange.NAME, name); - expectedExchnageEntry.put(Exchange.TYPE, type); - expectedExchnageEntry.put(Exchange.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name()); - return expectedExchnageEntry; - } - - private Map<UUID, UpgradeConfiguredObjectRecord> loadConfiguredObjects() - { - final Map<UUID, UpgradeConfiguredObjectRecord> configuredObjectsRecords = new HashMap<UUID, UpgradeConfiguredObjectRecord>(); - final ConfiguredObjectBinding binding = new ConfiguredObjectBinding(); - final UpgradeUUIDBinding uuidBinding = new UpgradeUUIDBinding(); - CursorOperation configuredObjectsCursor = new CursorOperation() - { - @Override - public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, - DatabaseEntry key, DatabaseEntry value) - { - UUID id = uuidBinding.entryToObject(key); - UpgradeConfiguredObjectRecord object = binding.entryToObject(value); - configuredObjectsRecords.put(id, object); - } - }; - new DatabaseTemplate(_environment, CONFIGURED_OBJECTS_DB_NAME, null).run(configuredObjectsCursor); - return configuredObjectsRecords; - } - - private void assertContent() - { - final NewDataBinding contentBinding = new NewDataBinding(); - CursorOperation contentCursorOperation = new CursorOperation() - { - - @Override - public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, - DatabaseEntry key, DatabaseEntry value) - { - long id = LongBinding.entryToLong(key); - assertTrue("Unexpected id", id > 0); - byte[] content = contentBinding.entryToObject(value); - assertNotNull("Unexpected content", content); - } - }; - new DatabaseTemplate(_environment, NEW_CONTENT_DB_NAME, null).run(contentCursorOperation); - } -} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom7To8Test.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom7To8Test.java deleted file mode 100644 index fc7142e9e4..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom7To8Test.java +++ /dev/null @@ -1,378 +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.upgrade; - -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 java.util.Map.Entry; -import java.util.UUID; - -import org.apache.qpid.server.model.Binding; -import org.apache.qpid.server.model.Exchange; -import org.apache.qpid.server.model.LifetimePolicy; -import org.apache.qpid.server.model.Queue; -import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.util.MapJsonSerializer; - -import com.sleepycat.bind.tuple.TupleBinding; -import com.sleepycat.bind.tuple.TupleInput; -import com.sleepycat.bind.tuple.TupleOutput; -import com.sleepycat.je.Database; -import com.sleepycat.je.DatabaseEntry; -import com.sleepycat.je.Transaction; - -public class UpgradeFrom7To8Test extends AbstractUpgradeTestCase -{ - private static final String ARGUMENTS = "arguments"; - - private static final String CONFIGURED_OBJECTS_DB_NAME = "CONFIGURED_OBJECTS"; - private static final String CONFIGURED_OBJECT_HIERARCHY_DB_NAME = "CONFIGURED_OBJECT_HIERARCHY"; - - @Override - public VirtualHost<?,?,?> getVirtualHost() - { - VirtualHost<?,?,?> virtualHost = mock(VirtualHost.class); - when(virtualHost.getName()).thenReturn("test"); - return virtualHost; - } - - @Override - protected String getStoreDirectoryName() - { - return "bdbstore-v7"; - } - - public void testPerformUpgrade() throws Exception - { - UpgradeFrom7To8 upgrade = new UpgradeFrom7To8(); - upgrade.performUpgrade(_environment, UpgradeInteractionHandler.DEFAULT_HANDLER, getVirtualHost()); - - assertDatabaseRecordCount(CONFIGURED_OBJECTS_DB_NAME, 11); - assertDatabaseRecordCount(CONFIGURED_OBJECT_HIERARCHY_DB_NAME, 13); - - assertConfiguredObjects(); - assertConfiguredObjectHierarchy(); - } - - - private void assertConfiguredObjectHierarchy() - { - Map<UpgradeHierarchyKey, UUID> hierarchy = loadConfiguredObjectHierarchy(); - assertEquals("Unexpected number of configured objects", 13, hierarchy.size()); - - UUID vhUuid = UUIDGenerator.generateVhostUUID(getVirtualHost().getName()); - UUID myExchUuid = UUIDGenerator.generateExchangeUUID("myexch", getVirtualHost().getName()); - UUID amqDirectUuid = UUIDGenerator.generateExchangeUUID("amq.direct", getVirtualHost().getName()); - UUID queue1Uuid = UUIDGenerator.generateQueueUUID("queue1", getVirtualHost().getName()); - UUID queue1ToAmqDirectBindingUuid = UUIDGenerator.generateBindingUUID("amq.direct", "queue1", "queue1", getVirtualHost().getName()); - - // myexch -> virtualhost - UpgradeHierarchyKey myExchToVhParent = new UpgradeHierarchyKey(myExchUuid, VirtualHost.class.getSimpleName()); - assertExpectedHierarchyEntry(hierarchy, myExchToVhParent, vhUuid); - - // queue1 -> virtualhost - UpgradeHierarchyKey queue1ToVhParent = new UpgradeHierarchyKey(queue1Uuid, VirtualHost.class.getSimpleName()); - assertExpectedHierarchyEntry(hierarchy, queue1ToVhParent, vhUuid); - - // queue1binding -> amq.direct - // queue1binding -> queue1 - UpgradeHierarchyKey queue1BindingToAmqDirect = new UpgradeHierarchyKey(queue1ToAmqDirectBindingUuid, Exchange.class.getSimpleName()); - UpgradeHierarchyKey queue1BindingToQueue1 = new UpgradeHierarchyKey(queue1ToAmqDirectBindingUuid, Queue.class.getSimpleName()); - assertExpectedHierarchyEntry(hierarchy, queue1BindingToAmqDirect, amqDirectUuid); - assertExpectedHierarchyEntry(hierarchy, queue1BindingToQueue1, queue1Uuid); - - String[] defaultExchanges = {"amq.topic", "amq.fanout", "amq.direct", "amq.match"}; - for (String exchangeName : defaultExchanges) - { - UUID id = UUIDGenerator.generateExchangeUUID(exchangeName, getVirtualHost().getName()); - UpgradeHierarchyKey exchangeParent = new UpgradeHierarchyKey(id, VirtualHost.class.getSimpleName()); - assertExpectedHierarchyEntry(hierarchy, exchangeParent, vhUuid); - } - - } - - private void assertExpectedHierarchyEntry( - Map<UpgradeHierarchyKey, UUID> hierarchy, - UpgradeHierarchyKey childHierarchyKey, UUID parentUUID) - { - assertTrue("Expected hierarchy entry does not exist", hierarchy.containsKey(childHierarchyKey)); - assertEquals("Expected hierarchy entry does not exist", parentUUID, hierarchy.get(childHierarchyKey)); - } - - - private void assertConfiguredObjects() - { - Map<UUID, UpgradeConfiguredObjectRecord> configuredObjects = loadConfiguredObjects(); - assertEquals("Unexpected number of configured objects", 11, configuredObjects.size()); - - Map<UUID, Map<String, Object>> expected = new HashMap<UUID, Map<String, Object>>(); - - String configVersion = "0.3"; - expected.putAll(createExpectedVirtualHost(configVersion)); - - expected.putAll(createExpectedQueue("queue1", Boolean.FALSE, null, null)); - expected.putAll(createExpectedQueue("queue2", Boolean.FALSE, null, null)); - - expected.putAll(createExpectedExchangeMap("myexch", "direct")); - - expected.putAll(createExpectedBindingMap("queue1", "queue1", "amq.direct", null)); - expected.putAll(createExpectedBindingMap("queue1", "queue1", "myexch", null)); - expected.putAll(createExpectedBindingMap("queue2", "queue2", "amq.fanout", null)); - - expected.putAll(createExpectedExchangeMap("amq.direct", "direct")); - expected.putAll(createExpectedExchangeMap("amq.fanout", "fanout")); - expected.putAll(createExpectedExchangeMap("amq.match", "headers")); - expected.putAll(createExpectedExchangeMap("amq.topic", "topic")); - - MapJsonSerializer jsonSerializer = new MapJsonSerializer(); - for (Entry<UUID, UpgradeConfiguredObjectRecord> entry : configuredObjects.entrySet()) - { - UpgradeConfiguredObjectRecord object = entry.getValue(); - - UUID actualKey = entry.getKey(); - String actualType = object.getType(); - String actualJson = object.getAttributes(); - Map<String, Object> actualDeserializedAttributes = jsonSerializer.deserialize(actualJson); - - assertTrue("Entry UUID " + actualKey + " of type " + actualType + " is unexpected", expected.containsKey(actualKey)); - - Map<String, Object> expectedDeserializedAttributes = expected.get(actualKey); - - assertEquals("Entry UUID " + actualKey + " of type " + actualType + " has uenxpected deserialised value, json was: " + actualJson, - expectedDeserializedAttributes, actualDeserializedAttributes); - } - } - - private Map<UUID, Map<String, Object>> createExpectedVirtualHost(String modelVersion) - { - Map<String, Object> expectedVirtualHostEntry = new HashMap<String, Object>(); - expectedVirtualHostEntry.put("modelVersion", modelVersion); - expectedVirtualHostEntry.put(VirtualHost.NAME, getVirtualHost().getName()); - - UUID expectedUUID = UUIDGenerator.generateVhostUUID(getVirtualHost().getName()); - return Collections.singletonMap(expectedUUID, expectedVirtualHostEntry); - } - - private Map<UUID, Map<String, Object>> createExpectedQueue(String queueName, boolean exclusiveFlag, String owner, Map<String, Object> argumentMap) - { - Map<String, Object> expectedQueueEntry = new HashMap<String, Object>(); - expectedQueueEntry.put(Queue.NAME, queueName); - expectedQueueEntry.put(Queue.EXCLUSIVE, exclusiveFlag); - expectedQueueEntry.put(Queue.OWNER, owner); - expectedQueueEntry.put(Queue.TYPE, "standard"); - - if (argumentMap != null) - { - expectedQueueEntry.put(ARGUMENTS, argumentMap); - } - UUID expectedUUID = UUIDGenerator.generateQueueUUID(queueName, getVirtualHost().getName()); - return Collections.singletonMap(expectedUUID, expectedQueueEntry); - } - - private Map<UUID, Map<String, Object>> createExpectedExchangeMap(String exchangeName, String type) - { - Map<String, Object> expectedExchangeMap = new HashMap<String, Object>(); - expectedExchangeMap.put(Exchange.NAME, exchangeName); - expectedExchangeMap.put(Exchange.TYPE, type); - expectedExchangeMap.put(Exchange.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name()); - UUID expectedUUID = UUIDGenerator.generateExchangeUUID(exchangeName, getVirtualHost().getName()); - return Collections.singletonMap(expectedUUID, expectedExchangeMap); - } - - private Map<UUID, Map<String, Object>> createExpectedBindingMap(String queueName, String bindingName, String exchangeName, Map<String, String> argumentMap) - { - Map<String, Object> expectedBinding = new HashMap<String, Object>(); - expectedBinding.put(Binding.NAME, bindingName); - expectedBinding.put(Binding.ARGUMENTS, argumentMap == null ? Collections.emptyMap() : argumentMap); - - UUID expectedUUID = UUIDGenerator.generateBindingUUID(exchangeName, queueName, bindingName, getVirtualHost().getName()); - return Collections.singletonMap(expectedUUID, expectedBinding); - } - - private Map<UUID, UpgradeConfiguredObjectRecord> loadConfiguredObjects() - { - final Map<UUID, UpgradeConfiguredObjectRecord> configuredObjectsRecords = new HashMap<UUID, UpgradeConfiguredObjectRecord>(); - final UpgradeConfiguredObjectBinding binding = new UpgradeConfiguredObjectBinding(); - final UpgradeUUIDBinding uuidBinding = new UpgradeUUIDBinding(); - CursorOperation configuredObjectsCursor = new CursorOperation() - { - @Override - public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, - DatabaseEntry key, DatabaseEntry value) - { - UUID id = uuidBinding.entryToObject(key); - UpgradeConfiguredObjectRecord object = binding.entryToObject(value); - configuredObjectsRecords.put(id, object); - } - }; - new DatabaseTemplate(_environment, CONFIGURED_OBJECTS_DB_NAME, null).run(configuredObjectsCursor); - return configuredObjectsRecords; - } - - - private Map<UpgradeHierarchyKey, UUID> loadConfiguredObjectHierarchy() - { - final Map<UpgradeHierarchyKey, UUID> hierarchyRecords = new HashMap<UpgradeHierarchyKey, UUID>(); - final UpgradeHierarchyKeyBinding hierarchyKeyBinding = new UpgradeHierarchyKeyBinding(); - final UpgradeUUIDBinding uuidParentBinding = new UpgradeUUIDBinding(); - CursorOperation hierarchyCursor = new CursorOperation() - { - @Override - public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, - DatabaseEntry key, DatabaseEntry value) - { - UpgradeHierarchyKey hierarchyKey = hierarchyKeyBinding.entryToObject(key); - UUID parentId = uuidParentBinding.entryToObject(value); - hierarchyRecords.put(hierarchyKey, parentId); - } - }; - new DatabaseTemplate(_environment, CONFIGURED_OBJECT_HIERARCHY_DB_NAME, null).run(hierarchyCursor); - return hierarchyRecords; - } - - private static class UpgradeConfiguredObjectBinding extends TupleBinding<UpgradeConfiguredObjectRecord> - { - @Override - public UpgradeConfiguredObjectRecord entryToObject(TupleInput tupleInput) - { - String type = tupleInput.readString(); - String json = tupleInput.readString(); - UpgradeConfiguredObjectRecord configuredObject = new UpgradeConfiguredObjectRecord(type, json); - return configuredObject; - } - - @Override - public void objectToEntry(UpgradeConfiguredObjectRecord object, TupleOutput tupleOutput) - { - throw new UnsupportedOperationException(); - } - } - - private static class UpgradeConfiguredObjectRecord - { - private final String _attributes; - private final String _type; - - public UpgradeConfiguredObjectRecord(String type, String attributes) - { - super(); - _attributes = attributes; - _type = type; - } - - public String getAttributes() - { - return _attributes; - } - - public String getType() - { - return _type; - } - - } - - private static class UpgradeUUIDBinding extends TupleBinding<UUID> - { - @Override - public UUID entryToObject(final TupleInput tupleInput) - { - return new UUID(tupleInput.readLong(), tupleInput.readLong()); - } - - @Override - public void objectToEntry(final UUID uuid, final TupleOutput tupleOutput) - { - throw new UnsupportedOperationException(); - } - } - - private static class UpgradeHierarchyKeyBinding extends TupleBinding<UpgradeHierarchyKey> - { - @Override - public UpgradeHierarchyKey entryToObject(TupleInput tupleInput) - { - UUID childId = new UUID(tupleInput.readLong(), tupleInput.readLong()); - String parentType = tupleInput.readString(); - - return new UpgradeHierarchyKey(childId, parentType); - } - - @Override - public void objectToEntry(UpgradeHierarchyKey hk, TupleOutput tupleOutput) - { - throw new UnsupportedOperationException(); - } - } - - private static class UpgradeHierarchyKey - { - private final UUID _childId; - private final String _parentType; - - public UpgradeHierarchyKey(final UUID childId, final String parentType) - { - _childId = childId; - _parentType = parentType; - } - - @Override - public boolean equals(final Object o) - { - if (this == o) - { - return true; - } - if (o == null || getClass() != o.getClass()) - { - return false; - } - - final UpgradeHierarchyKey that = (UpgradeHierarchyKey) o; - - if (!_childId.equals(that._childId)) - { - return false; - } - if (!_parentType.equals(that._parentType)) - { - return false; - } - - return true; - } - - @Override - public int hashCode() - { - int result = _childId.hashCode(); - result = 31 * result + _parentType.hashCode(); - return result; - } - - } - -} 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 deleted file mode 100644 index 5b869b67dc..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderFailOnNewerVersionTest.java +++ /dev/null @@ -1,102 +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.upgrade; - -import com.sleepycat.bind.tuple.IntegerBinding; -import com.sleepycat.je.Cursor; -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.BDBConfigurationStore; -import org.apache.qpid.server.util.ServerScopedRuntimeException; - -public class UpgraderFailOnNewerVersionTest extends AbstractUpgradeTestCase -{ - private Upgrader _upgrader; - - @Override - protected String getStoreDirectoryName() - { - return "bdbstore-v999"; - } - - @Override - public void setUp() throws Exception - { - super.setUp(); - _upgrader = new Upgrader(_environment, getVirtualHost()); - } - - private int getStoreVersion() - { - DatabaseConfig dbConfig = new DatabaseConfig(); - dbConfig.setTransactional(true); - dbConfig.setAllowCreate(true); - int storeVersion = -1; - Database versionDb = null; - Cursor cursor = null; - try - { - versionDb = _environment.openDatabase(null, Upgrader.VERSION_DB_NAME, dbConfig); - cursor = versionDb.openCursor(null, null); - DatabaseEntry key = new DatabaseEntry(); - DatabaseEntry value = new DatabaseEntry(); - while (cursor.getNext(key, value, null) == OperationStatus.SUCCESS) - { - int version = IntegerBinding.entryToInt(key); - if (storeVersion < version) - { - storeVersion = version; - } - } - } - finally - { - if (cursor != null) - { - cursor.close(); - } - if (versionDb != null) - { - versionDb.close(); - } - } - return storeVersion; - } - - public void testUpgrade() throws Exception - { - assertEquals("Unexpected store version", 999, getStoreVersion()); - try - { - _upgrader.upgradeIfNecessary(); - fail("Store should not be able to be upgraded"); - } - catch(ServerScopedRuntimeException ex) - { - assertEquals("Incorrect exception thrown", "Database version 999 is higher than the most recent known version: " - + BDBConfigurationStore.VERSION, ex.getMessage()); - } - } - -} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderTest.java deleted file mode 100644 index 54dd08fd98..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderTest.java +++ /dev/null @@ -1,146 +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.upgrade; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import org.apache.qpid.server.store.berkeleydb.BDBConfigurationStore; -import org.apache.qpid.server.store.berkeleydb.tuple.ContentBinding; - -import com.sleepycat.bind.tuple.IntegerBinding; -import com.sleepycat.bind.tuple.LongBinding; -import com.sleepycat.je.Cursor; -import com.sleepycat.je.Database; -import com.sleepycat.je.DatabaseConfig; -import com.sleepycat.je.DatabaseEntry; -import com.sleepycat.je.Environment; -import com.sleepycat.je.OperationStatus; -import com.sleepycat.je.Transaction; - -public class UpgraderTest extends AbstractUpgradeTestCase -{ - private Upgrader _upgrader; - - @Override - protected String getStoreDirectoryName() - { - return "bdbstore-v4"; - } - - @Override - public void setUp() throws Exception - { - super.setUp(); - _upgrader = new Upgrader(_environment, getVirtualHost()); - } - - private int getStoreVersion(Environment environment) - { - DatabaseConfig dbConfig = new DatabaseConfig(); - dbConfig.setTransactional(true); - dbConfig.setAllowCreate(true); - int storeVersion = -1; - Database versionDb = null; - Cursor cursor = null; - try - { - versionDb = environment.openDatabase(null, Upgrader.VERSION_DB_NAME, dbConfig); - cursor = versionDb.openCursor(null, null); - DatabaseEntry key = new DatabaseEntry(); - DatabaseEntry value = new DatabaseEntry(); - while (cursor.getNext(key, value, null) == OperationStatus.SUCCESS) - { - int version = IntegerBinding.entryToInt(key); - if (storeVersion < version) - { - storeVersion = version; - } - } - } - finally - { - if (cursor != null) - { - cursor.close(); - } - if (versionDb != null) - { - versionDb.close(); - } - } - return storeVersion; - } - - public void testUpgrade() throws Exception - { - assertEquals("Unexpected store version", -1, getStoreVersion(_environment)); - _upgrader.upgradeIfNecessary(); - assertEquals("Unexpected store version", BDBConfigurationStore.VERSION, getStoreVersion(_environment)); - assertContent(); - } - - public void testEmptyDatabaseUpgradeDoesNothing() throws Exception - { - File nonExistentStoreLocation = new File(TMP_FOLDER, getName()); - deleteDirectoryIfExists(nonExistentStoreLocation); - - nonExistentStoreLocation.mkdir(); - Environment emptyEnvironment = createEnvironment(nonExistentStoreLocation); - try - { - _upgrader = new Upgrader(emptyEnvironment, getVirtualHost()); - _upgrader.upgradeIfNecessary(); - - List<String> databaseNames = emptyEnvironment.getDatabaseNames(); - List<String> expectedDatabases = new ArrayList<String>(); - expectedDatabases.add(Upgrader.VERSION_DB_NAME); - assertEquals("Expectedonly VERSION table in initially empty store after upgrade: ", expectedDatabases, databaseNames); - assertEquals("Unexpected store version", BDBConfigurationStore.VERSION, getStoreVersion(emptyEnvironment)); - - } - finally - { - emptyEnvironment.close(); - nonExistentStoreLocation.delete(); - } - } - - private void assertContent() - { - final ContentBinding contentBinding = ContentBinding.getInstance(); - CursorOperation contentCursorOperation = new CursorOperation() - { - - @Override - public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction, DatabaseEntry key, - DatabaseEntry value) - { - long id = LongBinding.entryToLong(key); - assertTrue("Unexpected id", id > 0); - byte[] content = contentBinding.entryToObject(value); - assertNotNull("Unexpected content", content); - } - }; - new DatabaseTemplate(_environment, "MESSAGE_CONTENT", null).run(contentCursorOperation); - } -} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHostImplTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHostImplTest.java deleted file mode 100644 index 24a2ddb071..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHostImplTest.java +++ /dev/null @@ -1,109 +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.virtualhost.berkeleydb; - -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.UUID; - -import org.apache.qpid.server.configuration.IllegalConfigurationException; -import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor; -import org.apache.qpid.server.configuration.updater.TaskExecutor; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.BrokerModel; -import org.apache.qpid.server.model.VirtualHostNode; -import org.apache.qpid.server.store.DurableConfigurationStore; -import org.apache.qpid.server.util.BrokerTestHelper; -import org.apache.qpid.test.utils.QpidTestCase; -import org.apache.qpid.test.utils.TestFileUtils; -import org.apache.qpid.util.FileUtils; - -public class BDBVirtualHostImplTest extends QpidTestCase -{ - private File _storePath; - private VirtualHostNode<?> _node; - - @Override - public void setUp() throws Exception - { - super.setUp(); - Broker broker = BrokerTestHelper.createBrokerMock(); - - TaskExecutor taskExecutor = CurrentThreadTaskExecutor.newStartedInstance(); - when(broker.getTaskExecutor()).thenReturn(taskExecutor); - when(broker.getChildExecutor()).thenReturn(taskExecutor); - - - _storePath = TestFileUtils.createTestDirectory(); - - _node = mock(VirtualHostNode.class); - when(_node.getParent(Broker.class)).thenReturn(broker); - when(_node.getModel()).thenReturn(BrokerModel.getInstance()); - when(_node.getTaskExecutor()).thenReturn(taskExecutor); - when(_node.getChildExecutor()).thenReturn(taskExecutor); - when(_node.getConfigurationStore()).thenReturn(mock(DurableConfigurationStore.class)); - when(_node.getId()).thenReturn(UUID.randomUUID()); - } - - @Override - public void tearDown() throws Exception - { - try - { - if (_storePath != null) - { - FileUtils.delete(_storePath, true); - } - } - finally - { - super.tearDown(); - } - } - - public void testValidateOnCreateForInvalidStorePath() throws Exception - { - String hostName = getTestName(); - File file = new File(_storePath + File.separator + hostName); - assertTrue("Empty file is not created", file.createNewFile()); - Map<String, Object> attributes = new HashMap<>(); - attributes.put(BDBVirtualHost.ID, UUID.randomUUID()); - attributes.put(BDBVirtualHost.TYPE, BDBVirtualHostImpl.VIRTUAL_HOST_TYPE); - attributes.put(BDBVirtualHost.NAME, hostName); - attributes.put(BDBVirtualHost.STORE_PATH, file.getAbsoluteFile()); - - BDBVirtualHostImpl host = new BDBVirtualHostImpl(attributes, _node); - try - { - host.create(); - fail("Cannot create DBD virtual host from existing empty file"); - } - catch (IllegalConfigurationException e) - { - assertTrue("Unexpected exception " + e.getMessage(), e.getMessage().startsWith("Cannot open virtual host message store")); - } - } - -} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeTest.java deleted file mode 100644 index 4fe2bdc97f..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeTest.java +++ /dev/null @@ -1,160 +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.virtualhostnode.berkeleydb; - -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.security.AccessControlException; -import java.util.HashMap; -import java.util.Map; - -import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor; -import org.apache.qpid.server.configuration.updater.TaskExecutor; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.ConfiguredObjectFactory; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.model.VirtualHostNode; -import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.store.DurableConfigurationStore; -import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacade; -import org.apache.qpid.server.util.BrokerTestHelper; -import org.apache.qpid.test.utils.QpidTestCase; - -public class BDBHARemoteReplicationNodeTest extends QpidTestCase -{ - private final org.apache.qpid.server.security.SecurityManager _mockSecurityManager = mock(SecurityManager.class); - - private Broker _broker; - private TaskExecutor _taskExecutor; - private BDBHAVirtualHostNode<?> _virtualHostNode; - private DurableConfigurationStore _configStore; - private ReplicatedEnvironmentFacade _facade; - - @Override - protected void setUp() throws Exception - { - super.setUp(); - - _facade = mock(ReplicatedEnvironmentFacade.class); - - _broker = BrokerTestHelper.createBrokerMock(); - - _taskExecutor = new CurrentThreadTaskExecutor(); - _taskExecutor.start(); - when(_broker.getTaskExecutor()).thenReturn(_taskExecutor); - when(_broker.getChildExecutor()).thenReturn(_taskExecutor); - - _virtualHostNode = mock(BDBHAVirtualHostNode.class); - _configStore = mock(DurableConfigurationStore.class); - when(_virtualHostNode.getConfigurationStore()).thenReturn(_configStore); - - // Virtualhost needs the EventLogger from the SystemContext. - when(_virtualHostNode.getParent(Broker.class)).thenReturn(_broker); - doReturn(VirtualHostNode.class).when(_virtualHostNode).getCategoryClass(); - ConfiguredObjectFactory objectFactory = _broker.getObjectFactory(); - when(_virtualHostNode.getModel()).thenReturn(objectFactory.getModel()); - when(_virtualHostNode.getTaskExecutor()).thenReturn(_taskExecutor); - when(_virtualHostNode.getChildExecutor()).thenReturn(_taskExecutor); - - } - - public void testUpdateRole() - { - String remoteReplicationName = getName(); - BDBHARemoteReplicationNode remoteReplicationNode = createRemoteReplicationNode(remoteReplicationName); - - remoteReplicationNode.setAttribute(BDBHARemoteReplicationNode.ROLE, remoteReplicationNode.getRole(), NodeRole.MASTER); - - verify(_facade).transferMasterAsynchronously(remoteReplicationName); - } - - public void testDelete() - { - String remoteReplicationName = getName(); - BDBHARemoteReplicationNode remoteReplicationNode = createRemoteReplicationNode(remoteReplicationName); - - remoteReplicationNode.delete(); - - verify(_facade).removeNodeFromGroup(remoteReplicationName); - } - - // *************** ReplicationNode Access Control Tests *************** - - public void testUpdateDeniedByACL() - { - when(_broker.getSecurityManager()).thenReturn(_mockSecurityManager); - - String remoteReplicationName = getName(); - BDBHARemoteReplicationNode remoteReplicationNode = createRemoteReplicationNode(remoteReplicationName); - - doThrow(new AccessControlException("mocked ACL exception")).when(_mockSecurityManager).authoriseUpdate(remoteReplicationNode); - - assertNull(remoteReplicationNode.getDescription()); - - try - { - remoteReplicationNode.setAttribute(VirtualHost.DESCRIPTION, null, "My description"); - fail("Exception not thrown"); - } - catch (AccessControlException ace) - { - // PASS - } - } - - public void testDeleteDeniedByACL() - { - when(_broker.getSecurityManager()).thenReturn(_mockSecurityManager); - - String remoteReplicationName = getName(); - BDBHARemoteReplicationNode remoteReplicationNode = createRemoteReplicationNode(remoteReplicationName); - - doThrow(new AccessControlException("mocked ACL exception")).when(_mockSecurityManager).authoriseDelete(remoteReplicationNode); - - assertNull(remoteReplicationNode.getDescription()); - - try - { - remoteReplicationNode.delete(); - fail("Exception not thrown"); - } - catch (AccessControlException ace) - { - // PASS - } - } - - private BDBHARemoteReplicationNode createRemoteReplicationNode(final String replicationNodeName) - { - Map<String, Object> attributes = new HashMap<>(); - attributes.put(BDBHARemoteReplicationNode.NAME, replicationNodeName); - attributes.put(BDBHARemoteReplicationNode.MONITOR, Boolean.FALSE); - - BDBHARemoteReplicationNodeImpl node = new BDBHARemoteReplicationNodeImpl(_virtualHostNode, attributes, _facade); - node.create(); - return node; - } - - -} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeOperationalLoggingTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeOperationalLoggingTest.java deleted file mode 100644 index 6d740568ab..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeOperationalLoggingTest.java +++ /dev/null @@ -1,444 +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.virtualhostnode.berkeleydb; - -import static org.mockito.Matchers.argThat; -import static org.mockito.Mockito.*; - -import java.util.Collections; -import java.util.EnumSet; -import java.util.Map; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import org.apache.qpid.server.logging.EventLogger; -import org.apache.qpid.server.logging.LogMessage; -import org.apache.qpid.server.logging.LogSubject; -import org.apache.qpid.server.logging.messages.HighAvailabilityMessages; -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.model.SystemConfig; -import org.apache.qpid.server.store.berkeleydb.NoopConfigurationChangeListener; -import org.apache.qpid.test.utils.PortHelper; -import org.apache.qpid.test.utils.QpidTestCase; -import org.hamcrest.Description; -import org.mockito.ArgumentMatcher; - -/** - * Class to test that specific VHN operations result in the expected Operational Log message(s) being performed. - */ -public class BDBHAVirtualHostNodeOperationalLoggingTest extends QpidTestCase -{ - private BDBHAVirtualHostNodeTestHelper _helper; - private EventLogger _eventLogger; - private PortHelper _portHelper = new PortHelper(); - - @Override - protected void setUp() throws Exception - { - super.setUp(); - _helper = new BDBHAVirtualHostNodeTestHelper(getTestName()); - _eventLogger = mock(EventLogger.class); - SystemConfig<?> context = (SystemConfig<?>) _helper.getBroker().getParent(SystemConfig.class); - when(context.getEventLogger()).thenReturn(_eventLogger); - } - - @Override - protected void tearDown() throws Exception - { - try - { - _helper.tearDown(); - } - finally - { - super.tearDown(); - } - - _portHelper.waitUntilAllocatedPortsAreFree(); - } - - public void testCreate() throws Exception - { - int node1PortNumber = _portHelper.getNextAvailable(); - String helperAddress = "localhost:" + node1PortNumber; - String groupName = "group"; - String nodeName = "node1"; - - Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, node1PortNumber); - BDBHAVirtualHostNodeImpl node1 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node1Attributes); - - _helper.assertNodeRole(node1, NodeRole.MASTER); - - // stop node to avoid running into race when role change is reported after we performed the check - node1.stop(); - - assertEquals("Unexpected VHN log subject", "[grp(/group)/vhn(/node1)] ", node1.getVirtualHostNodeLogSubject().getLogString()); - assertEquals("Unexpected group log subject", "[grp(/group)] ", node1.getGroupLogSubject().getLogString()); - - String expectedMessage = HighAvailabilityMessages.CREATED().toString(); - verify(_eventLogger).message(argThat(new LogSubjectMatcher(node1.getVirtualHostNodeLogSubject())), - argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.CREATED_LOG_HIERARCHY))); - - expectedMessage = HighAvailabilityMessages.ROLE_CHANGED(node1.getName(), node1.getAddress(), NodeRole.WAITING.name(), NodeRole.MASTER.name()).toString(); - verify(_eventLogger).message(argThat(new LogSubjectMatcher(node1.getGroupLogSubject())), - argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.ROLE_CHANGED_LOG_HIERARCHY))); - } - - public void testDelete() throws Exception - { - int node1PortNumber = _portHelper.getNextAvailable(); - String helperAddress = "localhost:" + node1PortNumber; - String groupName = "group"; - String nodeName = "node1"; - - Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, node1PortNumber); - BDBHAVirtualHostNodeImpl node1 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node1Attributes); - _helper.assertNodeRole(node1, NodeRole.MASTER); - - reset(_eventLogger); - - node1.delete(); - - String expectedMessage = HighAvailabilityMessages.DELETED().toString(); - verify(_eventLogger).message(argThat(new LogSubjectMatcher(node1.getVirtualHostNodeLogSubject())), - argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.DELETED_LOG_HIERARCHY))); - - } - - public void testSetPriority() throws Exception - { - int node1PortNumber = _portHelper.getNextAvailable(); - String helperAddress = "localhost:" + node1PortNumber; - String groupName = "group"; - String nodeName = "node1"; - - Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, node1PortNumber); - BDBHAVirtualHostNodeImpl node1 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node1Attributes); - _helper.assertNodeRole(node1, NodeRole.MASTER); - - reset(_eventLogger); - - node1.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.PRIORITY, 10)); - - // make sure that task executor thread finishes all scheduled tasks - node1.stop(); - - String expectedMessage = HighAvailabilityMessages.PRIORITY_CHANGED("10").toString(); - verify(_eventLogger).message(argThat(new LogSubjectMatcher(node1.getVirtualHostNodeLogSubject())), - argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.PRIORITY_CHANGED_LOG_HIERARCHY))); - } - - public void testSetQuorumOverride() throws Exception - { - int node1PortNumber = _portHelper.getNextAvailable(); - String helperAddress = "localhost:" + node1PortNumber; - String groupName = "group"; - String nodeName = "node1"; - - Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, node1PortNumber); - BDBHAVirtualHostNodeImpl node1 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node1Attributes); - _helper.assertNodeRole(node1, NodeRole.MASTER); - - reset(_eventLogger); - - node1.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.QUORUM_OVERRIDE, 1)); - - // make sure that task executor thread finishes all scheduled tasks - node1.stop(); - - String expectedMessage = HighAvailabilityMessages.QUORUM_OVERRIDE_CHANGED("1").toString(); - verify(_eventLogger).message(argThat(new LogSubjectMatcher(node1.getVirtualHostNodeLogSubject())), - argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.QUORUM_OVERRIDE_CHANGED_LOG_HIERARCHY))); - } - - public void testSetDesignatedPrimary() throws Exception - { - int node1PortNumber = _portHelper.getNextAvailable(); - String helperAddress = "localhost:" + node1PortNumber; - String groupName = "group"; - String nodeName = "node1"; - - Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, node1PortNumber); - BDBHAVirtualHostNodeImpl node1 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node1Attributes); - _helper.assertNodeRole(node1, NodeRole.MASTER); - - reset(_eventLogger); - - node1.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.DESIGNATED_PRIMARY, true)); - - // make sure that task executor thread finishes all scheduled tasks - node1.stop(); - - String expectedMessage = HighAvailabilityMessages.DESIGNATED_PRIMARY_CHANGED("true").toString(); - verify(_eventLogger).message(argThat(new LogSubjectMatcher(node1.getVirtualHostNodeLogSubject())), - argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.DESIGNATED_PRIMARY_CHANGED_LOG_HIERARCHY))); - } - - public void testRemoteNodeAdded() throws Exception - { - int node1PortNumber = _portHelper.getNextAvailable(); - int node2PortNumber = _portHelper.getNextAvailable(); - String helperAddress = "localhost:" + node1PortNumber; - String groupName = "group"; - String nodeName = "node1"; - - Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, node1PortNumber, node2PortNumber); - BDBHAVirtualHostNodeImpl node1 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node1Attributes); - _helper.assertNodeRole(node1, NodeRole.MASTER); - - reset(_eventLogger); - - - Map<String, Object> node2Attributes = _helper.createNodeAttributes("node2", groupName, "localhost:" + node2PortNumber, helperAddress, nodeName); - BDBHAVirtualHostNodeImpl node2 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node2Attributes); - _helper.awaitRemoteNodes(node1, 1); - - // make sure that task executor thread finishes all scheduled tasks - node2.stop(); - - // Verify ADDED message from node1 when it discovers node2 has been added - String expectedMessage = HighAvailabilityMessages.ADDED(node2.getName(), node2.getAddress()).toString(); - verify(_eventLogger).message(argThat(new LogSubjectMatcher(node1.getGroupLogSubject())), - argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.ADDED_LOG_HIERARCHY))); - } - - public void testRemoteNodeRemoved() throws Exception - { - int node1PortNumber = _portHelper.getNextAvailable(); - int node2PortNumber = _portHelper.getNextAvailable(); - String helperAddress = "localhost:" + node1PortNumber; - String groupName = "group"; - String nodeName = "node1"; - - Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, node1PortNumber, node2PortNumber); - node1Attributes.put(BDBHAVirtualHostNode.DESIGNATED_PRIMARY, true); - BDBHAVirtualHostNodeImpl node1 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node1Attributes); - _helper.assertNodeRole(node1, NodeRole.MASTER); - - resetEventLogger(); - - Map<String, Object> node2Attributes = _helper.createNodeAttributes("node2", groupName, "localhost:" + node2PortNumber, helperAddress, nodeName); - BDBHAVirtualHostNodeImpl node2 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node2Attributes); - _helper.awaitRemoteNodes(node1, 1); - - reset(_eventLogger); - - node2.delete(); - _helper.awaitRemoteNodes(node1, 0); - - // make sure that task executor thread finishes all scheduled tasks - node1.stop(); - - String expectedMessage = HighAvailabilityMessages.REMOVED(node2.getName(), node2.getAddress()).toString(); - verify(_eventLogger).message(argThat(new LogSubjectMatcher(node1.getGroupLogSubject())), - argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.REMOVED_LOG_HIERARCHY))); - } - - public void testRemoteNodeDetached() throws Exception - { - int node1PortNumber = _portHelper.getNextAvailable(); - int node2PortNumber = _portHelper.getNextAvailable(); - String helperAddress = "localhost:" + node1PortNumber; - String groupName = "group"; - String nodeName = "node1"; - - Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, node1PortNumber, node2PortNumber); - node1Attributes.put(BDBHAVirtualHostNode.DESIGNATED_PRIMARY, true); - BDBHAVirtualHostNodeImpl node1 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node1Attributes); - - final CountDownLatch remoteNodeAdded = new CountDownLatch(1); - node1.addChangeListener(new NoopConfigurationChangeListener() - { - @Override - public void childAdded(ConfiguredObject<?> object, ConfiguredObject<?> child) - { - if (child instanceof BDBHARemoteReplicationNode) - { - remoteNodeAdded.countDown(); - } - } - }); - Map<String, Object> node2Attributes = _helper.createNodeAttributes("node2", groupName, "localhost:" + node2PortNumber, helperAddress, nodeName); - BDBHAVirtualHostNodeImpl node2 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node2Attributes); - - assertTrue("Remote node was not added during expected period of time", remoteNodeAdded.await(10, TimeUnit.SECONDS)); - - - BDBHARemoteReplicationNodeImpl remoteNode = (BDBHARemoteReplicationNodeImpl)node1.getRemoteReplicationNodes().iterator().next(); - waitForRemoteNodeToAttainRole(remoteNode, EnumSet.of(NodeRole.REPLICA)); - - - reset(_eventLogger); - - // close remote node - node2.close(); - - - waitForRemoteNodeToAttainRole(remoteNode, EnumSet.of(NodeRole.UNREACHABLE)); - - // make sure that task executor thread finishes all scheduled tasks - node1.stop(); - - // verify that remaining node issues the DETACHED operational logging for remote node - String expectedMessage = HighAvailabilityMessages.LEFT(node2.getName(), node2.getAddress()).toString(); - verify(_eventLogger).message(argThat(new LogSubjectMatcher(node1.getGroupLogSubject())), - argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.LEFT_LOG_HIERARCHY))); - } - - - public void testRemoteNodeReAttached() throws Exception - { - int node1PortNumber = _portHelper.getNextAvailable(); - int node2PortNumber = _portHelper.getNextAvailable(); - String helperAddress = "localhost:" + node1PortNumber; - String groupName = "group"; - String nodeName = "node1"; - - Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, node1PortNumber, node2PortNumber); - node1Attributes.put(BDBHAVirtualHostNode.DESIGNATED_PRIMARY, true); - BDBHAVirtualHostNodeImpl node1 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node1Attributes); - _helper.assertNodeRole(node1, NodeRole.MASTER); - - resetEventLogger(); - - Map<String, Object> node2Attributes = _helper.createNodeAttributes("node2", groupName, "localhost:" + node2PortNumber, helperAddress, nodeName); - BDBHAVirtualHostNodeImpl node2 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node2Attributes); - _helper.awaitRemoteNodes(node1, 1); - - BDBHARemoteReplicationNodeImpl remoteNode = (BDBHARemoteReplicationNodeImpl)node1.getRemoteReplicationNodes().iterator().next(); - waitForRemoteNodeToAttainRole(remoteNode, EnumSet.of(NodeRole.REPLICA)); - - node2.close(); - - waitForRemoteNodeToAttainRole(remoteNode, EnumSet.of(NodeRole.UNREACHABLE)); - - reset(_eventLogger); - - node2Attributes.put(BDBHAVirtualHostNode.PERMITTED_NODES, - node1Attributes.get(BDBHAVirtualHostNode.PERMITTED_NODES)); - node2 = (BDBHAVirtualHostNodeImpl)_helper.recoverHaVHN(node2.getId(), node2Attributes); - _helper.assertNodeRole(node2, NodeRole.REPLICA, NodeRole.MASTER); - waitForRemoteNodeToAttainRole(remoteNode, EnumSet.of(NodeRole.REPLICA, NodeRole.MASTER)); - - // make sure that task executor thread finishes all scheduled tasks - node1.stop(); - - final String expectedMessage = HighAvailabilityMessages.JOINED(node2.getName(), node2.getAddress()).toString(); - verify(_eventLogger).message(argThat(new LogSubjectMatcher(node1.getGroupLogSubject())), - argThat(new LogMessageMatcher(expectedMessage, HighAvailabilityMessages.JOINED_LOG_HIERARCHY))); - } - - private void waitForRemoteNodeToAttainRole(BDBHARemoteReplicationNode remoteNode, EnumSet<NodeRole> desiredRoles) throws Exception - { - int counter = 0; - while (!desiredRoles.contains(remoteNode.getRole()) && counter<50) - { - Thread.sleep(100); - counter++; - } - } - - private EventLogger resetEventLogger() - { - EventLogger eventLogger = mock(EventLogger.class); - SystemConfig<?> context = (SystemConfig<?>) _helper.getBroker().getParent(SystemConfig.class); - when(context.getEventLogger()).thenReturn(eventLogger); - return eventLogger; - } - - class LogMessageMatcher extends ArgumentMatcher<LogMessage> - { - private String _expectedMessage; - private String _expectedMessageFailureDescription = null; - private String _expectedHierarchy; - private String _expectedHierarchyFailureDescription = null; - - public LogMessageMatcher(String expectedMessage, String expectedHierarchy) - { - _expectedMessage = expectedMessage; - _expectedHierarchy = expectedHierarchy; - } - - @Override - public boolean matches(Object argument) - { - LogMessage logMessage = (LogMessage)argument; - - boolean expectedMessageMatches = _expectedMessage.equals(logMessage.toString()); - if (!expectedMessageMatches) - { - _expectedMessageFailureDescription = "Expected message does not match. Expected: " + _expectedMessage + ", actual: " + logMessage.toString(); - } - boolean expectedHierarchyMatches = _expectedHierarchy.equals(logMessage.getLogHierarchy()); - if (!expectedHierarchyMatches) - { - _expectedHierarchyFailureDescription = "Expected hierarchy does not match. Expected: " + _expectedHierarchy + ", actual: " + logMessage.getLogHierarchy(); - } - - return expectedMessageMatches && expectedHierarchyMatches; - } - - @Override - public void describeTo(Description description) - { - if (_expectedMessageFailureDescription != null) - { - description.appendText(_expectedMessageFailureDescription); - } - if (_expectedHierarchyFailureDescription != null) - { - description.appendText(_expectedHierarchyFailureDescription); - } - } - } - - class LogSubjectMatcher extends ArgumentMatcher<LogSubject> - { - private LogSubject _logSubject; - private String _failureDescription = null; - - public LogSubjectMatcher(LogSubject logSubject) - { - _logSubject = logSubject; - } - - @Override - public boolean matches(Object argument) - { - final LogSubject logSubject = (LogSubject)argument; - final boolean foundAMatch = _logSubject.toLogString().equals(logSubject.toLogString()); - if (!foundAMatch) - { - _failureDescription = "LogSubject does not match. Expected: " + _logSubject.toLogString() + ", actual : " + logSubject.toLogString(); - } - return foundAMatch; - } - - @Override - public void describeTo(Description description) - { - if (_failureDescription != null) - { - description.appendText(_failureDescription); - } - } - } -} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java deleted file mode 100644 index 9d0e905fc5..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java +++ /dev/null @@ -1,350 +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.virtualhostnode.berkeleydb; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.when; - -import java.io.File; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -import com.sleepycat.je.rep.ReplicationConfig; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.map.SerializationConfig; - -import org.apache.qpid.server.configuration.updater.TaskExecutor; -import org.apache.qpid.server.configuration.updater.TaskExecutorImpl; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.BrokerModel; -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.model.ConfiguredObjectFactory; -import org.apache.qpid.server.model.RemoteReplicationNode; -import org.apache.qpid.server.model.State; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.model.VirtualHostNode; -import org.apache.qpid.server.store.ConfiguredObjectRecordImpl; -import org.apache.qpid.server.store.UnresolvedConfiguredObject; -import org.apache.qpid.server.util.BrokerTestHelper; -import org.apache.qpid.server.virtualhost.berkeleydb.BDBHAVirtualHostImpl; -import org.apache.qpid.server.virtualhostnode.AbstractVirtualHostNode; -import org.apache.qpid.test.utils.QpidTestCase; -import org.apache.qpid.util.FileUtils; - -/** - * Helper class to make the tests of BDB HA Virtual Host Nodes simpler and more concise. - */ -public class BDBHAVirtualHostNodeTestHelper -{ - private final String _testName; - private Broker<?> _broker; - private File _bdbStorePath; - private TaskExecutor _taskExecutor; - private final ConfiguredObjectFactory _objectFactory = BrokerModel.getInstance().getObjectFactory(); - private final Set<BDBHAVirtualHostNode<?>> _nodes = new HashSet<>(); - - public BDBHAVirtualHostNodeTestHelper(String testName) throws Exception - { - _testName = testName; - _broker = BrokerTestHelper.createBrokerMock(); - - _taskExecutor = new TaskExecutorImpl(); - _taskExecutor.start(); - when(_broker.getTaskExecutor()).thenReturn(_taskExecutor); - when(_broker.getChildExecutor()).thenReturn(_taskExecutor); - - - _bdbStorePath = new File(QpidTestCase.TMP_FOLDER, _testName + "." + System.currentTimeMillis()); - _bdbStorePath.deleteOnExit(); - } - - public void tearDown() throws Exception - { - try - { - Exception firstException = null; - for (VirtualHostNode<?> node : _nodes) - { - try - { - node.delete(); - } - catch(Exception e) - { - if (firstException != null) - { - firstException = e; - } - } - } - if (firstException != null) - { - throw firstException; - } - } - finally - { - if (_taskExecutor != null) - { - _taskExecutor.stopImmediately(); - } - if (_bdbStorePath != null) - { - FileUtils.delete(_bdbStorePath, true); - } - } - } - - public BDBHARemoteReplicationNode<?> findRemoteNode(BDBHAVirtualHostNode<?> node, String name) - { - for (RemoteReplicationNode<?> remoteNode : node.getRemoteReplicationNodes()) - { - if (remoteNode.getName().equals(name)) - { - return (BDBHARemoteReplicationNode<?>)remoteNode; - } - } - return null; - } - - public void awaitRemoteNodes(BDBHAVirtualHostNode<?> node, int expectedNodeNumber) throws InterruptedException - { - int counter = 0; - - @SuppressWarnings("rawtypes") - Collection<? extends RemoteReplicationNode> remoteNodes = null; - do - { - remoteNodes = node.getRemoteReplicationNodes(); - if (counter > 0) - { - Thread.sleep(100); - } - counter++; - } - // TODO: 30 seconds is quite a lot to wait, we need to reduce this limit - while(remoteNodes.size() != expectedNodeNumber && counter<100); - assertEquals("Unexpected node number", expectedNodeNumber, node.getRemoteReplicationNodes().size()); - } - - public void awaitForAttributeChange(ConfiguredObject<?> object, String name, Object expectedValue) throws InterruptedException - { - int awaitCounter = 0; - while(!object.equals(object.getAttribute(name)) && awaitCounter < 50) - { - Thread.sleep(100); - awaitCounter++; - } - assertEquals("Unexpected attribute " + name + " on " + object, expectedValue, object.getAttribute(name) ); - } - - public BDBHAVirtualHostNode<?> awaitAndFindNodeInRole(NodeRole desiredRole) throws InterruptedException - { - BDBHAVirtualHostNode<?> replica = null; - int findReplicaCount = 0; - while(replica == null) - { - replica = findNodeInRole(desiredRole); - if (replica == null) - { - Thread.sleep(100); - } - if (findReplicaCount > 50) - { - fail("Could not find a node in role " + desiredRole); - } - findReplicaCount++; - } - return replica; - } - - public BDBHAVirtualHostNode<?> findNodeInRole(NodeRole role) - { - for (BDBHAVirtualHostNode<?> node : _nodes) - { - if (role == node.getRole()) - { - return node; - } - } - return null; - } - - public BDBHAVirtualHostNode<?> createHaVHN(Map<String, Object> attributes) - { - @SuppressWarnings("unchecked") - BDBHAVirtualHostNode<?> node = (BDBHAVirtualHostNode<?>) _objectFactory.create(VirtualHostNode.class, attributes, _broker); - _nodes.add(node); - return node; - } - - public BDBHAVirtualHostNode<?> recoverHaVHN(UUID id, Map<String, Object> attributes) - { - Map<String,UUID> parents = new HashMap<>(); - parents.put(Broker.class.getSimpleName(),_broker.getId()); - ConfiguredObjectRecordImpl record = new ConfiguredObjectRecordImpl(id, VirtualHostNode.class.getSimpleName(), attributes, parents ); - - @SuppressWarnings("unchecked") - UnresolvedConfiguredObject<BDBHAVirtualHostNodeImpl> unresolved = _objectFactory.recover(record, _broker); - BDBHAVirtualHostNode<?> node = unresolved.resolve(); - node.open(); - _nodes.add(node); - return node; - } - - public void assertNodeRole(BDBHAVirtualHostNode<?> node, NodeRole... roleName) throws InterruptedException - { - int iterationCounter = 0; - boolean inRole =false; - do - { - for (NodeRole role : roleName) - { - if (role == node.getRole()) - { - inRole = true; - break; - } - } - if (!inRole) - { - Thread.sleep(50); - } - iterationCounter++; - } - while(!inRole && iterationCounter<100); - assertTrue("Node " + node.getName() + " did not transit into role " + Arrays.toString(roleName) - + " Node role is " + node.getRole(), inRole); - } - - public BDBHAVirtualHostNode<?> createAndStartHaVHN(Map<String, Object> attributes) throws InterruptedException - { - BDBHAVirtualHostNode<?> node = createHaVHN(attributes); - return startNodeAndWait(node); - } - - public BDBHAVirtualHostNode<?> startNodeAndWait(BDBHAVirtualHostNode<?> node) throws InterruptedException - { - node.start(); - assertNodeRole(node, NodeRole.MASTER, NodeRole.REPLICA); - assertEquals("Unexpected node state", State.ACTIVE, node.getState()); - return node; - } - - public String getMessageStorePath() - { - return _bdbStorePath.getAbsolutePath(); - } - - public Broker getBroker() - { - return _broker; - } - - public Map<String, Object> createNodeAttributes(String nodeName, String groupName, String address, - String helperAddress, String helperNodeNode, int... ports) - throws Exception - { - Map<String, Object> node1Attributes = new HashMap<String, Object>(); - node1Attributes.put(BDBHAVirtualHostNode.ID, UUID.randomUUID()); - node1Attributes.put(BDBHAVirtualHostNode.TYPE, BDBHAVirtualHostNodeImpl.VIRTUAL_HOST_NODE_TYPE); - node1Attributes.put(BDBHAVirtualHostNode.NAME, nodeName); - node1Attributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName); - node1Attributes.put(BDBHAVirtualHostNode.ADDRESS, address); - node1Attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress); - node1Attributes.put(BDBHAVirtualHostNode.STORE_PATH, getMessageStorePath() + File.separator + nodeName); - if (address.equals(helperAddress)) - { - node1Attributes.put(BDBHAVirtualHostNode.PERMITTED_NODES, getPermittedNodes(ports)); - } - else - { - node1Attributes.put(BDBHAVirtualHostNode.HELPER_NODE_NAME, helperNodeNode); - } - - Map<String, String> context = new HashMap<String, String>(); - context.put(ReplicationConfig.REPLICA_ACK_TIMEOUT, "2 s"); - context.put(ReplicationConfig.INSUFFICIENT_REPLICAS_TIMEOUT, "2 s"); - - if (ports != null) - { - String bluePrint = getBlueprint(); - node1Attributes.put(AbstractVirtualHostNode.VIRTUALHOST_INITIAL_CONFIGURATION, bluePrint); - } - - node1Attributes.put(BDBHAVirtualHostNode.CONTEXT, context); - - return node1Attributes; - } - - public static String getBlueprint() throws Exception - { - Map<String,Object> bluePrint = new HashMap<>(); - bluePrint.put(VirtualHost.TYPE, BDBHAVirtualHostImpl.VIRTUAL_HOST_TYPE); - - StringWriter writer = new StringWriter(); - ObjectMapper mapper = new ObjectMapper(); - mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); - mapper.writeValue(writer, bluePrint); - return writer.toString(); - } - - public static List<String> getPermittedNodes(int[] ports) - { - List<String> permittedNodes = new ArrayList<String>(); - for (int port:ports) - { - permittedNodes.add("localhost:" + port); - } - return permittedNodes; - } - - public void awaitForVirtualhost(final VirtualHostNode<?> node, final int wait) - { - long endTime = System.currentTimeMillis() + wait; - do - { - if(node.getVirtualHost() != null) - { - return; - } - try - { - Thread.sleep(100); - } - catch (InterruptedException e) - { - // ignore - } - } - while(System.currentTimeMillis() < endTime); - } -} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeTest.java deleted file mode 100644 index 812d9a3b19..0000000000 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeTest.java +++ /dev/null @@ -1,95 +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.virtualhostnode.berkeleydb; - -import static org.mockito.Mockito.when; - -import java.io.File; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import org.apache.qpid.server.configuration.IllegalConfigurationException; -import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor; -import org.apache.qpid.server.configuration.updater.TaskExecutor; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.util.BrokerTestHelper; -import org.apache.qpid.test.utils.QpidTestCase; -import org.apache.qpid.test.utils.TestFileUtils; -import org.apache.qpid.util.FileUtils; - -public class BDBVirtualHostNodeTest extends QpidTestCase -{ - private Broker<?> _broker; - private File _storePath; - - @Override - public void setUp() throws Exception - { - super.setUp(); - _broker = BrokerTestHelper.createBrokerMock(); - TaskExecutor taskExecutor = CurrentThreadTaskExecutor.newStartedInstance(); - when(_broker.getTaskExecutor()).thenReturn(taskExecutor); - when(_broker.getChildExecutor()).thenReturn(taskExecutor); - - _storePath = TestFileUtils.createTestDirectory(); - } - - @Override - public void tearDown() throws Exception - { - try - { - if (_storePath != null) - { - FileUtils.delete(_storePath, true); - } - } - finally - { - super.tearDown(); - } - } - - public void testValidateOnCreateForInvalidStorePath() throws Exception - { - String nodeName = getTestName(); - File file = new File(_storePath + File.separator + nodeName); - assertTrue("Empty file is not created", file.createNewFile()); - Map<String, Object> attributes = new HashMap<>(); - attributes.put(BDBVirtualHostNode.ID, UUID.randomUUID()); - attributes.put(BDBVirtualHostNode.TYPE, BDBVirtualHostNodeImpl.VIRTUAL_HOST_NODE_TYPE); - attributes.put(BDBVirtualHostNode.NAME, nodeName); - attributes.put(BDBVirtualHostNode.STORE_PATH, file.getAbsolutePath()); - - BDBVirtualHostNodeImpl node = new BDBVirtualHostNodeImpl(attributes, _broker); - try - { - node.create(); - fail("Cannot create DBD node from existing empty file"); - } - catch (IllegalConfigurationException e) - { - assertTrue("Unexpected exception " + e.getMessage(), e.getMessage().startsWith("Cannot open node configuration store")); - } - } - -} diff --git a/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v4/test-store/00000000.jdb b/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v4/test-store/00000000.jdb Binary files differdeleted file mode 100644 index cfc1f05d28..0000000000 --- a/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v4/test-store/00000000.jdb +++ /dev/null diff --git a/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/readme.txt b/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/readme.txt deleted file mode 100644 index a7e754f967..0000000000 --- a/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/readme.txt +++ /dev/null @@ -1,5 +0,0 @@ -The bdbstore v5 data were obtained by upgrading the bdbstore v4 data as part of running -test UpgradeFrom4to5Test#testPerformUpgradeWithHandlerAnsweringNo. - -The rationale for not using BDBStoreUpgradeTestPreparer in this case is that we need chunked content. -Current implementation of BDBMessageStore only stores messages in one chunk.
\ No newline at end of file diff --git a/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000000.jdb b/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000000.jdb Binary files differdeleted file mode 100644 index cfc1f05d28..0000000000 --- a/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000000.jdb +++ /dev/null diff --git a/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000001.jdb b/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000001.jdb Binary files differdeleted file mode 100644 index 4b45ff61e6..0000000000 --- a/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000001.jdb +++ /dev/null diff --git a/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v7/readme.txt b/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v7/readme.txt deleted file mode 100644 index efb929c944..0000000000 --- a/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v7/readme.txt +++ /dev/null @@ -1,6 +0,0 @@ -The bdbstore v7 data was obtained by running 0.26 and: - -* creating an exchange 'myexch' of type direct -* creating queues 'queue1' and 'queue2' -* binding 'queue1' to 'myexch' and 'amq.direct' using binding key 'queue1' -* binding 'queue2' to amq.fanout only using binding key 'queue2'
\ No newline at end of file diff --git a/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v7/test-store/00000000.jdb b/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v7/test-store/00000000.jdb Binary files differdeleted file mode 100644 index 4957f86e1a..0000000000 --- a/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v7/test-store/00000000.jdb +++ /dev/null diff --git a/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v999/test-store/00000000.jdb b/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v999/test-store/00000000.jdb Binary files differdeleted file mode 100644 index 991367019f..0000000000 --- a/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v999/test-store/00000000.jdb +++ /dev/null |
