/* * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package org.mule.runtime.core.util.queue; import org.mule.runtime.api.exception.MuleRuntimeException; import org.mule.runtime.core.util.xa.ResourceManagerException; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.collections.CollectionUtils; /** * Transaction context for transient queues */ public class TransientQueueTransactionContext implements LocalQueueTransactionContext { public static final int CLEAR_POLL_TIMEOUT = 10; private Map<QueueStore, List<Serializable>> added; private Map<QueueStore, List<Serializable>> removed; public boolean offer(QueueStore queue, Serializable item, long offerTimeout) throws InterruptedException { initializeAdded(); List<Serializable> queueAdded = lookupAddedQueue(queue); // wait for enough room if (queue.offer(null, queueAdded.size(), offerTimeout)) { queueAdded.add(item); return true; } else { return false; } } public void untake(QueueStore queue, Serializable item) throws InterruptedException { initializeAdded(); List<Serializable> queueAdded = lookupAddedQueue(queue); queueAdded.add(item); } public void clear(QueueStore queue) throws InterruptedException { this.initializeRemoved(); List<Serializable> queueRemoved = this.lookupRemovedQueue(queue); for (Serializable discardedItem = queue.poll(CLEAR_POLL_TIMEOUT); discardedItem != null; discardedItem = queue.poll(CLEAR_POLL_TIMEOUT)) { queueRemoved.add(discardedItem); } if (this.added != null) { List<Serializable> queueAdded = this.lookupAddedQueue(queue); if (!CollectionUtils.isEmpty(queueAdded)) { queueRemoved.addAll(queueAdded); queueAdded.clear(); } } } public Serializable poll(QueueStore queue, long pollTimeout) throws InterruptedException { Serializable value = queue.poll(pollTimeout); if (value != null) { if (removed == null) { removed = new HashMap<QueueStore, List<Serializable>>(); } List<Serializable> queueRemoved = removed.get(queue); if (queueRemoved == null) { queueRemoved = new ArrayList<Serializable>(); removed.put(queue, queueRemoved); } queueRemoved.add(value); } return value; } public Serializable peek(QueueStore queue) throws InterruptedException { return queue.peek(); } public int size(QueueStore queue) { int sz = queue.getSize(); if (added != null) { List<Serializable> queueAdded = added.get(queue); if (queueAdded != null) { sz += queueAdded.size(); } } return sz; } @Override public void doCommit() throws ResourceManagerException { try { if (added != null) { for (Map.Entry<QueueStore, List<Serializable>> entry : added.entrySet()) { QueueStore queue = entry.getKey(); List<Serializable> queueAdded = entry.getValue(); if (queueAdded != null && queueAdded.size() > 0) { for (Serializable object : queueAdded) { queue.putNow(object); } } } } } catch (Exception e) { throw new ResourceManagerException(e); } finally { added = null; removed = null; } } @Override public void doRollback() throws ResourceManagerException { if (removed != null) { for (Map.Entry<QueueStore, List<Serializable>> entry : removed.entrySet()) { QueueStore queue = entry.getKey(); List<Serializable> queueRemoved = entry.getValue(); if (queueRemoved != null && queueRemoved.size() > 0) { for (Serializable id : queueRemoved) { try { queue.putNow(id); } catch (InterruptedException e) { throw new MuleRuntimeException(e); } } } } } added = null; removed = null; } protected void initializeAdded() { if (added == null) { added = new HashMap<QueueStore, List<Serializable>>(); } } protected void initializeRemoved() { if (this.removed == null) { this.removed = new HashMap<QueueStore, List<Serializable>>(); } } protected List<Serializable> lookupAddedQueue(QueueStore queue) { List<Serializable> queueAdded = added.get(queue); if (queueAdded == null) { queueAdded = new ArrayList<Serializable>(); added.put(queue, queueAdded); } return queueAdded; } protected List<Serializable> lookupRemovedQueue(QueueStore queue) { List<Serializable> queueRemoved = this.removed.get(queue); if (queueRemoved == null) { queueRemoved = new ArrayList<Serializable>(); this.removed.put(queue, queueRemoved); } return queueRemoved; } }