Search in sources :

Example 1 with TransactionImpl

use of org.apache.activemq.artemis.core.transaction.impl.TransactionImpl in project activemq-artemis by apache.

the class AbstractJournalStorageManager method loadPreparedTransactions.

private void loadPreparedTransactions(final PostOffice postOffice, final PagingManager pagingManager, final ResourceManager resourceManager, final Map<Long, QueueBindingInfo> queueInfos, final List<PreparedTransactionInfo> preparedTransactions, final Map<SimpleString, List<Pair<byte[], Long>>> duplicateIDMap, final Map<Long, PageSubscription> pageSubscriptions, final Set<Pair<Long, Long>> pendingLargeMessages, JournalLoader journalLoader) throws Exception {
    // recover prepared transactions
    for (PreparedTransactionInfo preparedTransaction : preparedTransactions) {
        XidEncoding encodingXid = new XidEncoding(preparedTransaction.getExtraData());
        Xid xid = encodingXid.xid;
        Transaction tx = new TransactionImpl(preparedTransaction.getId(), xid, this);
        List<MessageReference> referencesToAck = new ArrayList<>();
        Map<Long, Message> messages = new HashMap<>();
        // first get any sent messages for this tx and recreate
        for (RecordInfo record : preparedTransaction.getRecords()) {
            byte[] data = record.data;
            ActiveMQBuffer buff = ActiveMQBuffers.wrappedBuffer(data);
            byte recordType = record.getUserRecordType();
            switch(recordType) {
                case JournalRecordIds.ADD_LARGE_MESSAGE:
                    {
                        messages.put(record.id, parseLargeMessage(messages, buff));
                        break;
                    }
                case JournalRecordIds.ADD_MESSAGE:
                    {
                        break;
                    }
                case JournalRecordIds.ADD_MESSAGE_PROTOCOL:
                    {
                        Message message = MessagePersister.getInstance().decode(buff, null);
                        messages.put(record.id, message);
                        break;
                    }
                case JournalRecordIds.ADD_REF:
                    {
                        long messageID = record.id;
                        RefEncoding encoding = new RefEncoding();
                        encoding.decode(buff);
                        Message message = messages.get(messageID);
                        if (message == null) {
                            throw new IllegalStateException("Cannot find message with id " + messageID);
                        }
                        journalLoader.handlePreparedSendMessage(message, tx, encoding.queueID);
                        break;
                    }
                case JournalRecordIds.ACKNOWLEDGE_REF:
                    {
                        long messageID = record.id;
                        RefEncoding encoding = new RefEncoding();
                        encoding.decode(buff);
                        journalLoader.handlePreparedAcknowledge(messageID, referencesToAck, encoding.queueID);
                        break;
                    }
                case JournalRecordIds.PAGE_TRANSACTION:
                    {
                        PageTransactionInfo pageTransactionInfo = new PageTransactionInfoImpl();
                        pageTransactionInfo.decode(buff);
                        if (record.isUpdate) {
                            PageTransactionInfo pgTX = pagingManager.getTransaction(pageTransactionInfo.getTransactionID());
                            pgTX.reloadUpdate(this, pagingManager, tx, pageTransactionInfo.getNumberOfMessages());
                        } else {
                            pageTransactionInfo.setCommitted(false);
                            tx.putProperty(TransactionPropertyIndexes.PAGE_TRANSACTION, pageTransactionInfo);
                            pagingManager.addTransaction(pageTransactionInfo);
                            tx.addOperation(new FinishPageMessageOperation());
                        }
                        break;
                    }
                case SET_SCHEDULED_DELIVERY_TIME:
                    {
                        break;
                    }
                case DUPLICATE_ID:
                    {
                        // We need load the duplicate ids at prepare time too
                        DuplicateIDEncoding encoding = new DuplicateIDEncoding();
                        encoding.decode(buff);
                        DuplicateIDCache cache = postOffice.getDuplicateIDCache(encoding.address);
                        cache.load(tx, encoding.duplID);
                        break;
                    }
                case ACKNOWLEDGE_CURSOR:
                    {
                        CursorAckRecordEncoding encoding = new CursorAckRecordEncoding();
                        encoding.decode(buff);
                        encoding.position.setRecordID(record.id);
                        PageSubscription sub = locateSubscription(encoding.queueID, pageSubscriptions, queueInfos, pagingManager);
                        if (sub != null) {
                            sub.reloadPreparedACK(tx, encoding.position);
                            referencesToAck.add(new PagedReferenceImpl(encoding.position, null, sub));
                        } else {
                            ActiveMQServerLogger.LOGGER.journalCannotFindQueueReloadingACK(encoding.queueID);
                        }
                        break;
                    }
                case PAGE_CURSOR_COUNTER_VALUE:
                    {
                        ActiveMQServerLogger.LOGGER.journalPAGEOnPrepared();
                        break;
                    }
                case PAGE_CURSOR_COUNTER_INC:
                    {
                        PageCountRecordInc encoding = new PageCountRecordInc();
                        encoding.decode(buff);
                        PageSubscription sub = locateSubscription(encoding.getQueueID(), pageSubscriptions, queueInfos, pagingManager);
                        if (sub != null) {
                            sub.getCounter().applyIncrementOnTX(tx, record.id, encoding.getValue(), encoding.getPersistentSize());
                            sub.notEmpty();
                        } else {
                            ActiveMQServerLogger.LOGGER.journalCannotFindQueueReloadingACK(encoding.getQueueID());
                        }
                        break;
                    }
                default:
                    {
                        ActiveMQServerLogger.LOGGER.journalInvalidRecordType(recordType);
                    }
            }
        }
        for (RecordInfo recordDeleted : preparedTransaction.getRecordsToDelete()) {
            byte[] data = recordDeleted.data;
            if (data.length > 0) {
                ActiveMQBuffer buff = ActiveMQBuffers.wrappedBuffer(data);
                byte b = buff.readByte();
                switch(b) {
                    case ADD_LARGE_MESSAGE_PENDING:
                        {
                            long messageID = buff.readLong();
                            if (!pendingLargeMessages.remove(new Pair<>(recordDeleted.id, messageID))) {
                                ActiveMQServerLogger.LOGGER.largeMessageNotFound(recordDeleted.id);
                            }
                            installLargeMessageConfirmationOnTX(tx, recordDeleted.id);
                            break;
                        }
                    default:
                        ActiveMQServerLogger.LOGGER.journalInvalidRecordTypeOnPreparedTX(b);
                }
            }
        }
        journalLoader.handlePreparedTransaction(tx, referencesToAck, xid, resourceManager);
    }
}
Also used : PreparedTransactionInfo(org.apache.activemq.artemis.core.journal.PreparedTransactionInfo) PageTransactionInfo(org.apache.activemq.artemis.core.paging.PageTransactionInfo) DuplicateIDCache(org.apache.activemq.artemis.core.postoffice.DuplicateIDCache) LargeServerMessage(org.apache.activemq.artemis.core.server.LargeServerMessage) Message(org.apache.activemq.artemis.api.core.Message) LinkedHashMap(java.util.LinkedHashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) PageTransactionInfoImpl(org.apache.activemq.artemis.core.paging.impl.PageTransactionInfoImpl) ArrayList(java.util.ArrayList) DuplicateIDEncoding(org.apache.activemq.artemis.core.persistence.impl.journal.codec.DuplicateIDEncoding) ActiveMQBuffer(org.apache.activemq.artemis.api.core.ActiveMQBuffer) RecordInfo(org.apache.activemq.artemis.core.journal.RecordInfo) PagedReferenceImpl(org.apache.activemq.artemis.core.paging.cursor.PagedReferenceImpl) TransactionImpl(org.apache.activemq.artemis.core.transaction.impl.TransactionImpl) PageSubscription(org.apache.activemq.artemis.core.paging.cursor.PageSubscription) MessageReference(org.apache.activemq.artemis.core.server.MessageReference) Xid(javax.transaction.xa.Xid) Transaction(org.apache.activemq.artemis.core.transaction.Transaction) FinishPageMessageOperation(org.apache.activemq.artemis.core.persistence.impl.journal.codec.FinishPageMessageOperation) CursorAckRecordEncoding(org.apache.activemq.artemis.core.persistence.impl.journal.codec.CursorAckRecordEncoding) XidEncoding(org.apache.activemq.artemis.core.persistence.impl.journal.codec.XidEncoding) PageCountRecordInc(org.apache.activemq.artemis.core.persistence.impl.journal.codec.PageCountRecordInc) RefEncoding(org.apache.activemq.artemis.core.persistence.impl.journal.codec.RefEncoding)

Example 2 with TransactionImpl

use of org.apache.activemq.artemis.core.transaction.impl.TransactionImpl in project activemq-artemis by apache.

the class PageSubscriptionImpl method cleanupEntries.

/**
 * It will cleanup all the records for completed pages
 */
@Override
public void cleanupEntries(final boolean completeDelete) throws Exception {
    if (completeDelete) {
        counter.delete();
    }
    if (logger.isTraceEnabled()) {
        logger.trace("cleanupEntries", new Exception("trace"));
    }
    Transaction tx = new TransactionImpl(store);
    boolean persist = false;
    final ArrayList<PageCursorInfo> completedPages = new ArrayList<>();
    // First get the completed pages using a lock
    synchronized (consumedPages) {
        // lastAckedPosition = null means no acks were done yet, so we are not ready to cleanup
        if (lastAckedPosition == null) {
            return;
        }
        for (Entry<Long, PageCursorInfo> entry : consumedPages.entrySet()) {
            PageCursorInfo info = entry.getValue();
            if (info.isDone() && !info.isPendingDelete()) {
                Page currentPage = pageStore.getCurrentPage();
                if (currentPage != null && entry.getKey() == pageStore.getCurrentPage().getPageId() && currentPage.isLive()) {
                    logger.trace("We can't clear page " + entry.getKey() + " now since it's the current page");
                } else {
                    info.setPendingDelete();
                    completedPages.add(entry.getValue());
                }
            }
        }
    }
    for (PageCursorInfo infoPG : completedPages) {
        // first will mark the page as complete
        if (isPersistent()) {
            PagePosition completePage = new PagePositionImpl(infoPG.getPageId(), infoPG.getNumberOfMessages());
            infoPG.setCompleteInfo(completePage);
            store.storePageCompleteTransactional(tx.getID(), this.getId(), completePage);
            if (!persist) {
                persist = true;
                tx.setContainsPersistent();
            }
        }
        // it will delete the page ack records
        for (PagePosition pos : infoPG.acks) {
            if (pos.getRecordID() >= 0) {
                store.deleteCursorAcknowledgeTransactional(tx.getID(), pos.getRecordID());
                if (!persist) {
                    // only need to set it once
                    tx.setContainsPersistent();
                    persist = true;
                }
            }
        }
        infoPG.acks.clear();
        infoPG.acks = Collections.synchronizedSet(new LinkedHashSet<PagePosition>());
        infoPG.removedReferences.clear();
        infoPG.removedReferences = new ConcurrentHashSet<>();
    }
    tx.addOperation(new TransactionOperationAbstract() {

        @Override
        public void afterCommit(final Transaction tx1) {
            executor.execute(new Runnable() {

                @Override
                public void run() {
                    if (!completeDelete) {
                        cursorProvider.scheduleCleanup();
                    }
                }
            });
        }
    });
    tx.commit();
}
Also used : LinkedHashSet(java.util.LinkedHashSet) ArrayList(java.util.ArrayList) Page(org.apache.activemq.artemis.core.paging.impl.Page) TransactionImpl(org.apache.activemq.artemis.core.transaction.impl.TransactionImpl) ActiveMQException(org.apache.activemq.artemis.api.core.ActiveMQException) TransactionOperationAbstract(org.apache.activemq.artemis.core.transaction.TransactionOperationAbstract) Transaction(org.apache.activemq.artemis.core.transaction.Transaction) AtomicLong(java.util.concurrent.atomic.AtomicLong) PagePosition(org.apache.activemq.artemis.core.paging.cursor.PagePosition)

Example 3 with TransactionImpl

use of org.apache.activemq.artemis.core.transaction.impl.TransactionImpl in project activemq-artemis by apache.

the class PageSubscriptionCounterImpl method delete.

@Override
public void delete() throws Exception {
    Transaction tx = new TransactionImpl(storage);
    delete(tx);
    tx.commit();
}
Also used : Transaction(org.apache.activemq.artemis.core.transaction.Transaction) TransactionImpl(org.apache.activemq.artemis.core.transaction.impl.TransactionImpl)

Example 4 with TransactionImpl

use of org.apache.activemq.artemis.core.transaction.impl.TransactionImpl in project activemq-artemis by apache.

the class PageSubscriptionCounterImpl method cleanupNonTXCounters.

/**
 * Cleanup temporary page counters on non transactional paged messages
 *
 * @param pageID
 */
@Override
public void cleanupNonTXCounters(final long pageID) throws Exception {
    PendingCounter pendingInfo;
    synchronized (this) {
        pendingInfo = pendingCounters.remove(pageID);
    }
    if (pendingInfo != null) {
        final int valueCleaned = pendingInfo.getCount();
        final long valueSizeCleaned = pendingInfo.getPersistentSize();
        Transaction tx = new TransactionImpl(storage);
        storage.deletePendingPageCounter(tx.getID(), pendingInfo.getId());
        // To apply the increment of the value just being cleaned
        increment(tx, valueCleaned, valueSizeCleaned);
        tx.addOperation(new TransactionOperationAbstract() {

            @Override
            public void afterCommit(Transaction tx) {
                pendingValue.addAndGet(-valueCleaned);
                pendingPersistentSize.updateAndGet(val -> val >= valueSizeCleaned ? val - valueSizeCleaned : 0);
            }
        });
        tx.commit();
    }
}
Also used : AtomicIntegerFieldUpdater(java.util.concurrent.atomic.AtomicIntegerFieldUpdater) PageSubscriptionCounter(org.apache.activemq.artemis.core.paging.cursor.PageSubscriptionCounter) Executor(java.util.concurrent.Executor) Transaction(org.apache.activemq.artemis.core.transaction.Transaction) Logger(org.jboss.logging.Logger) HashMap(java.util.HashMap) AtomicLongFieldUpdater(java.util.concurrent.atomic.AtomicLongFieldUpdater) ArrayList(java.util.ArrayList) Page(org.apache.activemq.artemis.core.paging.impl.Page) AtomicLong(java.util.concurrent.atomic.AtomicLong) TransactionOperationAbstract(org.apache.activemq.artemis.core.transaction.TransactionOperationAbstract) TransactionImpl(org.apache.activemq.artemis.core.transaction.impl.TransactionImpl) TransactionOperation(org.apache.activemq.artemis.core.transaction.TransactionOperation) Map(java.util.Map) PageSubscription(org.apache.activemq.artemis.core.paging.cursor.PageSubscription) StorageManager(org.apache.activemq.artemis.core.persistence.StorageManager) ActiveMQServerLogger(org.apache.activemq.artemis.core.server.ActiveMQServerLogger) LinkedList(java.util.LinkedList) TransactionPropertyIndexes(org.apache.activemq.artemis.core.transaction.TransactionPropertyIndexes) Transaction(org.apache.activemq.artemis.core.transaction.Transaction) TransactionImpl(org.apache.activemq.artemis.core.transaction.impl.TransactionImpl) TransactionOperationAbstract(org.apache.activemq.artemis.core.transaction.TransactionOperationAbstract)

Example 5 with TransactionImpl

use of org.apache.activemq.artemis.core.transaction.impl.TransactionImpl in project activemq-artemis by apache.

the class PageCursorProviderImpl method onPageModeCleared.

/**
 * Delete everything associated with any queue on this address.
 * This is to be called when the address is about to be released from paging.
 * Hence the PagingStore will be holding a write lock, meaning no messages are going to be paged at this time.
 * So, we shouldn't lock anything after this method, to avoid dead locks between the writeLock and any synchronization with the CursorProvider.
 */
@Override
public void onPageModeCleared() {
    ArrayList<PageSubscription> subscriptions = cloneSubscriptions();
    Transaction tx = new TransactionImpl(storageManager);
    for (PageSubscription sub : subscriptions) {
        try {
            sub.onPageModeCleared(tx);
        } catch (Exception e) {
            ActiveMQServerLogger.LOGGER.errorCleaningPagingOnQueue(e, sub.getQueue().getName().toString());
        }
    }
    try {
        tx.commit();
    } catch (Exception e) {
        ActiveMQServerLogger.LOGGER.errorCleaningPagingDuringCommit(e);
    }
}
Also used : Transaction(org.apache.activemq.artemis.core.transaction.Transaction) PageSubscription(org.apache.activemq.artemis.core.paging.cursor.PageSubscription) TransactionImpl(org.apache.activemq.artemis.core.transaction.impl.TransactionImpl)

Aggregations

TransactionImpl (org.apache.activemq.artemis.core.transaction.impl.TransactionImpl)31 Transaction (org.apache.activemq.artemis.core.transaction.Transaction)24 SimpleString (org.apache.activemq.artemis.api.core.SimpleString)11 MessageReference (org.apache.activemq.artemis.core.server.MessageReference)11 Test (org.junit.Test)10 Queue (org.apache.activemq.artemis.core.server.Queue)9 Message (org.apache.activemq.artemis.api.core.Message)8 PageSubscriptionCounter (org.apache.activemq.artemis.core.paging.cursor.PageSubscriptionCounter)7 StorageManager (org.apache.activemq.artemis.core.persistence.StorageManager)7 ArrayList (java.util.ArrayList)6 HashMap (java.util.HashMap)6 ActiveMQException (org.apache.activemq.artemis.api.core.ActiveMQException)5 PageSubscription (org.apache.activemq.artemis.core.paging.cursor.PageSubscription)5 DuplicateIDCache (org.apache.activemq.artemis.core.postoffice.DuplicateIDCache)5 BindingsTransactionImpl (org.apache.activemq.artemis.core.transaction.impl.BindingsTransactionImpl)5 Map (java.util.Map)4 ClientSession (org.apache.activemq.artemis.api.core.client.ClientSession)4 ClientSessionFactory (org.apache.activemq.artemis.api.core.client.ClientSessionFactory)4 LinkedList (java.util.LinkedList)3 NoSuchElementException (java.util.NoSuchElementException)3