KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > cache > invalidation > InvalidationsTxGrouper


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.cache.invalidation;
23
24 import javax.transaction.Transaction JavaDoc;
25
26 import org.jboss.logging.Logger;
27 import org.jboss.tm.TransactionLocal;
28
29 import java.util.HashMap JavaDoc;
30 import javax.transaction.Synchronization JavaDoc;
31
32 import java.io.Serializable JavaDoc;
33 import java.util.HashSet JavaDoc;
34 import java.util.Iterator JavaDoc;
35 import java.util.Map JavaDoc;
36 import java.util.Set JavaDoc;
37
38 /**
39  * Utility class that can be used to group invalidations in a set of
40  * BatchInvalidations structure and only commit them alltogether at
41  * transaction commit-time.
42  * The invalidations are grouped (in this order):
43  * - by transaction
44  * - by InvalidationManager instance
45  * - by InvalidationGroup
46  * <p/>
47  * This object will manage the transaction registering by itself if not
48  * already done.
49  * Thus, once a transaction commits, it will prepare a set of BatchInvalidation
50  * collections (one for each InvalidationManager involved): on BI instance
51  * for each InvalidationGroup. Then it will call the IM.batchInvalidation
52  * method.
53  *
54  * @author <a HREF="mailto:sacha.labourey@cogito-info.ch">Sacha Labourey</a>.
55  * @version $Revision: 41310 $
56  * @see InvalidationManagerMBean
57  * @see BatchInvalidation
58  * @see InvalidatorSynchronization
59  */

60 public class InvalidationsTxGrouper
61 {
62
63    // Constants -----------------------------------------------------
64

65    // Attributes ----------------------------------------------------
66

67    // Static --------------------------------------------------------
68

69    private static final TransactionLocal synchLocal = new TransactionLocal();
70    static Logger log = Logger.getLogger(InvalidationsTxGrouper.class);
71
72    // Constructors --------------------------------------------------
73

74    // Public --------------------------------------------------------
75

76    public static void registerInvalidationSynchronization(Transaction JavaDoc tx, InvalidationGroup group, Serializable JavaDoc key)
77       throws Exception JavaDoc
78    {
79       InvalidatorSynchronization synch = (InvalidatorSynchronization) synchLocal.get(tx);
80       if(synch == null)
81       {
82          synch = new InvalidatorSynchronization(tx);
83          synchLocal.set(tx, synch);
84          // If there is no tx don't try to use it
85
if( tx != null )
86          tx.registerSynchronization(synch);
87       }
88       synch.addInvalidation(group, key);
89       // If there is no tx call afterCompletion
90
if( tx == null )
91          synch.afterCompletion(javax.transaction.Status.STATUS_NO_TRANSACTION);
92    }
93 }
94
95 class InvalidatorSynchronization
96    implements Synchronization JavaDoc
97 {
98    /**
99     * The transaction we follow.
100     */

101    protected Transaction JavaDoc tx;
102
103    /**
104     * The context we manage.
105     */

106    protected HashMap JavaDoc ids = new HashMap JavaDoc();
107
108    /**
109     * Create a new isynchronization instance.
110     */

111    InvalidatorSynchronization(Transaction JavaDoc tx)
112    {
113       this.tx = tx;
114    }
115
116    public void addInvalidation(InvalidationGroup group, Serializable JavaDoc key)
117    {
118       InvalidationManagerMBean im = group.getInvalidationManager();
119
120       // the grouping is (in order): by InvalidationManager, by InvalidationGroup
121
//
122

123       Map JavaDoc relatedInvalidationMgr;
124       synchronized(ids)
125       {
126          relatedInvalidationMgr = (HashMap JavaDoc) ids.get(im);
127          if(relatedInvalidationMgr == null)
128          {
129             relatedInvalidationMgr = new HashMap JavaDoc();
130             ids.put(im, relatedInvalidationMgr);
131          }
132       }
133
134       Set JavaDoc relatedInvalidations;
135       synchronized(relatedInvalidationMgr)
136       {
137          relatedInvalidations = (HashSet JavaDoc) relatedInvalidationMgr.get(group);
138          if(relatedInvalidations == null)
139          {
140             relatedInvalidations = new HashSet JavaDoc();
141             relatedInvalidationMgr.put(group, relatedInvalidations);
142          }
143       }
144
145       relatedInvalidations.add(key);
146    }
147
148    // Synchronization implementation -----------------------------
149

150    public void beforeCompletion()
151    {
152    }
153
154
155    public void afterCompletion(int status)
156    {
157       // This is an independent point of entry. We need to make sure the
158
// thread is associated with the right context class loader
159
//
160
ClassLoader JavaDoc oldCl = Thread.currentThread().getContextClassLoader();
161       Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
162
163       try
164       {
165          try
166          {
167             sendBatchInvalidations();
168          }
169          catch(Exception JavaDoc ex)
170          {
171             InvalidationsTxGrouper.log.warn("Failed sending invalidations messages", ex);
172          }
173       }
174       finally
175       {
176          Thread.currentThread().setContextClassLoader(oldCl);
177       }
178    }
179
180    protected void sendBatchInvalidations()
181    {
182       boolean trace = InvalidationsTxGrouper.log.isTraceEnabled();
183       if(trace)
184       {
185          InvalidationsTxGrouper.log.trace("Begin sendBatchInvalidations, tx=" + tx);
186       }
187       // we iterate over all InvalidationManager involved
188
//
189
Iterator JavaDoc imIter = ids.keySet().iterator();
190       while(imIter.hasNext())
191       {
192          InvalidationManagerMBean im = (InvalidationManagerMBean) imIter.next();
193
194          // get associated groups
195
//
196
HashMap JavaDoc relatedInvalidationMgr = (HashMap JavaDoc) ids.get(im);
197
198          BatchInvalidation[] bomb = new BatchInvalidation[relatedInvalidationMgr.size()];
199
200          Iterator JavaDoc groupsIter = relatedInvalidationMgr.keySet().iterator();
201          int i = 0;
202          while(groupsIter.hasNext())
203          {
204             InvalidationGroup group = (InvalidationGroup) groupsIter.next();
205             HashSet JavaDoc sourceIds = (HashSet JavaDoc) relatedInvalidationMgr.get(group);
206             String JavaDoc groupName = group.getGroupName();
207             if(trace)
208             {
209                InvalidationsTxGrouper.log.trace("Adding ids to bomb(" + groupName + "): " + sourceIds);
210             }
211             Serializable JavaDoc[] ids = new Serializable JavaDoc[sourceIds.size()];
212             sourceIds.toArray(ids);
213             BatchInvalidation batch = new BatchInvalidation(ids, groupName);
214
215             bomb[i] = batch;
216
217             i++;
218          }
219
220          // do the batch-invalidation for this IM
221
//
222
im.batchInvalidate(bomb);
223       }
224       if(trace)
225       {
226          InvalidationsTxGrouper.log.trace("End sendBatchInvalidations, tx=" + tx);
227       }
228
229       // Help the GC to remove this big structure
230
//
231
this.ids = null;
232    }
233 }
234
Popular Tags