View Javadoc

1   /*
2    * $Id: QueueTransactionContext.java 22855 2011-09-04 17:45:44Z mike.schilling $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.util.queue;
12  
13  import org.mule.api.store.ObjectStoreException;
14  import org.mule.util.xa.AbstractTransactionContext;
15  import org.mule.util.xa.ResourceManagerException;
16  
17  import java.io.Serializable;
18  import java.util.ArrayList;
19  import java.util.HashMap;
20  import java.util.List;
21  import java.util.Map;
22  
23  public class QueueTransactionContext extends AbstractTransactionContext
24  {
25      private final TransactionalQueueManager transactionalQueueManager;
26      private Map<QueueInfo, List<Serializable>> added;
27      private Map<QueueInfo, List<Serializable>> removed;
28  
29      public QueueTransactionContext(TransactionalQueueManager transactionalQueueManager)
30      {
31          super();
32          this.transactionalQueueManager = transactionalQueueManager;
33      }
34  
35      public boolean offer(QueueInfo queue, Serializable item, long offerTimeout) throws InterruptedException, ObjectStoreException
36      {
37          readOnly = false;
38          if (queue.canTakeFromStore())
39          {
40              queue.writeToObjectStore(item);
41              return true;
42          }
43  
44          initializeAdded();
45  
46          List<Serializable> queueAdded = lookupQueue(queue);
47          // wait for enough room
48          if (queue.offer(null, queueAdded.size(), offerTimeout))
49          {
50              queueAdded.add(item);
51              return true;
52          }
53          else
54          {
55              return false;
56          }
57      }
58  
59      public void untake(QueueInfo queue, Serializable item) throws InterruptedException, ObjectStoreException
60      {
61          readOnly = false;
62          if (queue.canTakeFromStore())
63          {
64              queue.writeToObjectStore(item);
65          }
66  
67          initializeAdded();
68  
69          List<Serializable> queueAdded = lookupQueue(queue);
70          queueAdded.add(item);
71      }
72  
73      public Serializable poll(QueueInfo queue, long pollTimeout) throws InterruptedException, ObjectStoreException
74      {
75          readOnly = false;
76          if (added != null)
77          {
78              List<Serializable> queueAdded = added.get(queue);
79              if (queueAdded != null && queueAdded.size() > 0)
80              {
81                  return queueAdded.remove(queueAdded.size() - 1);
82              }
83          }
84  
85          if (queue.canTakeFromStore())
86          {
87              // TODO: verify that the queue is transactional too
88              return queue.takeNextItemFromStore(timeout);
89          }
90  
91          Serializable key;
92          Serializable value = null;
93          try
94          {
95              key = queue.poll(pollTimeout);
96          }
97          catch (InterruptedException e)
98          {
99              if (!transactionalQueueManager.getMuleContext().isStopping())
100             {
101                 throw e;
102             }
103             // if disposing, ignore
104             return null;
105         }
106 
107         if (key != null)
108         {
109             if (removed == null)
110             {
111                 removed = new HashMap<QueueInfo, List<Serializable>>();
112             }
113             List<Serializable> queueRemoved = removed.get(queue);
114             if (queueRemoved == null)
115             {
116                 queueRemoved = new ArrayList<Serializable>();
117                 removed.put(queue, queueRemoved);
118             }
119             value = transactionalQueueManager.doLoad(queue, key);
120             if (value != null)
121             {
122                 queueRemoved.add(key);
123             }
124         }
125         return value;
126     }
127 
128     public Serializable peek(QueueInfo queue) throws InterruptedException, ObjectStoreException
129     {
130         readOnly = false;
131         if (added != null)
132         {
133             List<Serializable> queueAdded = added.get(queue);
134             if (queueAdded != null)
135             {
136                 return queueAdded.get(queueAdded.size() - 1);
137             }
138         }
139 
140         Serializable o = queue.peek();
141         if (o != null)
142         {
143             o = transactionalQueueManager.doLoad(queue, o);
144         }
145         return o;
146     }
147 
148     public int size(QueueInfo queue)
149     {
150         int sz = queue.getSize();
151         if (added != null)
152         {
153             List<Serializable> queueAdded = added.get(queue);
154             if (queueAdded != null)
155             {
156                 sz += queueAdded.size();
157             }
158         }
159         return sz;
160     }
161 
162     @Override
163     public void doCommit() throws ResourceManagerException
164     {
165         try
166         {
167             if (added != null)
168             {
169                 for (Map.Entry<QueueInfo, List<Serializable>> entry : added.entrySet())
170                 {
171                     QueueInfo queue = entry.getKey();
172                     List<Serializable> queueAdded = entry.getValue();
173                     if (queueAdded != null && queueAdded.size() > 0)
174                     {
175                         for (Serializable object : queueAdded)
176                         {
177                             Serializable id = transactionalQueueManager.doStore(queue, object);
178                             queue.putNow(id);
179                         }
180                     }
181                 }
182             }
183             if (removed != null)
184             {
185                 for (Map.Entry<QueueInfo, List<Serializable>> entry : removed.entrySet())
186                 {
187                     QueueInfo queue = entry.getKey();
188                     List<Serializable> queueRemoved = entry.getValue();
189                     if (queueRemoved != null && queueRemoved.size() > 0)
190                     {
191                         for (Serializable id : queueRemoved)
192                         {
193                             transactionalQueueManager.doRemove(queue, id);
194                         }
195                     }
196                 }
197             }
198         }
199         catch (Exception e)
200         {
201             throw new ResourceManagerException(e);
202         }
203         finally
204         {
205             added = null;
206             removed = null;
207         }
208 
209     }
210 
211     @Override
212     public void doRollback() throws ResourceManagerException
213     {
214         if (removed != null)
215         {
216             for (Map.Entry<QueueInfo, List<Serializable>> entry : removed.entrySet())
217             {
218                 QueueInfo queue = entry.getKey();
219                 List<Serializable> queueRemoved = entry.getValue();
220                 if (queueRemoved != null && queueRemoved.size() > 0)
221                 {
222                     for (Serializable id : queueRemoved)
223                     {
224                         queue.putNow(id);
225                     }
226                 }
227             }
228         }
229         added = null;
230         removed = null;
231     }
232 
233     protected void initializeAdded()
234     {
235         if (added == null)
236         {
237             added = new HashMap<QueueInfo, List<Serializable>>();
238         }
239     }
240 
241     protected List<Serializable> lookupQueue(QueueInfo queue)
242     {
243         List<Serializable> queueAdded = added.get(queue);
244         if (queueAdded == null)
245         {
246             queueAdded = new ArrayList<Serializable>();
247             added.put(queue, queueAdded);
248         }
249         return queueAdded;
250     }
251 }