KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb > BeanLockManager


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.ejb;
23
24 import java.util.HashMap JavaDoc;
25
26 import org.jboss.monitor.EntityLockMonitor;
27 import org.jboss.monitor.LockMonitor;
28 import org.jboss.logging.Logger;
29 import javax.naming.InitialContext JavaDoc;
30
31 /**
32  * Manages BeanLocks. All BeanLocks have a reference count.
33  * When the reference count goes to 0, the lock is released from the
34  * id -> lock mapping.
35  *
36  * @author <a HREF="bill@burkecentral.com">Bill Burke</a>
37  * @author <a HREF="marc.fleury@jboss.org">Marc Fleury</a>
38  * @author Scott.Stark@jboss.org
39  */

40 public class BeanLockManager
41 {
42    private static final int NUMBER_OF_INSTANCES=40;
43    private static Logger log = Logger.getLogger(BeanLockManager.class);
44
45    /** Multiple instances of hashMap to diminish locking contentions.
46     * Rules for accessing this are determined by {@link getHashMap(Object)}*/

47    private HashMap JavaDoc map[] = new HashMap JavaDoc[NUMBER_OF_INSTANCES];
48
49
50    /** The container this manager reports to */
51    private Container container;
52
53    /** Reentrancy of calls */
54    private boolean reentrant = false;
55    private int txTimeout = 5000;
56    /** The logging trace flag, only set in ctor */
57    private boolean trace;
58    public Class JavaDoc lockClass;
59    protected LockMonitor monitor = null;
60
61    private BeanLockManager()
62    {
63        for (int i=0;i<map.length;i++)
64        {
65            map[i] = new HashMap JavaDoc();
66        }
67    }
68    public BeanLockManager(Container container)
69    {
70       this();
71       this.container = container;
72       trace = log.isTraceEnabled();
73       try
74       {
75          InitialContext JavaDoc ctx = new InitialContext JavaDoc();
76          EntityLockMonitor elm = (EntityLockMonitor) ctx.lookup(EntityLockMonitor.JNDI_NAME);
77          String JavaDoc jndiName = container.getBeanMetaData().getContainerObjectNameJndiName();
78          monitor = elm.getEntityLockMonitor(jndiName);
79       }
80       catch (Exception JavaDoc ignored)
81       {
82          // Ignore the lack of an EntityLockMonitor
83
}
84    }
85
86    public LockMonitor getLockMonitor()
87    {
88       return monitor;
89    }
90
91    private HashMap JavaDoc getHashMap(Object JavaDoc id)
92    {
93        final int mapInUse = id.hashCode()%NUMBER_OF_INSTANCES;
94        if (mapInUse>0)
95        {
96            return map[mapInUse];
97        }
98        else
99        {
100            return map[mapInUse*-1];
101        }
102    }
103
104    /**
105     * returns the lock associated with the key passed. If there is
106     * no lock one is created this call also increments the number of
107     * references interested in Lock.
108     *
109     * WARNING: All access to this method MUST have an equivalent
110     * removeLockRef cleanup call, or this will create a leak in the map,
111     */

112    public BeanLock getLock(Object JavaDoc id)
113    {
114       if (id == null)
115          throw new IllegalArgumentException JavaDoc("Attempt to get lock ref with a null object");
116
117       HashMap JavaDoc mapInUse = getHashMap(id);
118
119       synchronized (mapInUse)
120       {
121         BeanLock lock = (BeanLock) mapInUse.get(id);
122         if (lock!=null)
123         {
124             lock.addRef();
125             return lock;
126         }
127       }
128
129       try
130       {
131           BeanLock lock2 = (BeanLock)createLock(id);
132           synchronized(mapInUse)
133           {
134               BeanLock lock = (BeanLock) mapInUse.get(id);
135               // in case of bad luck, this might happen
136
if (lock != null)
137               {
138                   lock.addRef();
139                   return lock;
140               }
141               mapInUse.put(id, lock2);
142               lock2.addRef();
143               return lock2;
144           }
145       }
146       catch (Exception JavaDoc e)
147       {
148           // schrouf: should we really proceed with lock object
149
// in case of exception ??
150
log.warn("Failed to initialize lock:"+id, e);
151           throw new RuntimeException JavaDoc (e);
152       }
153    }
154
155    private BeanLock createLock(Object JavaDoc id) throws Exception JavaDoc
156    {
157        BeanLock lock = (BeanLock) lockClass.newInstance();
158        lock.setId(id);
159        lock.setTimeout(txTimeout);
160        lock.setContainer(container);
161
162        return lock;
163    }
164
165    public void removeLockRef(Object JavaDoc id)
166    {
167       if (id == null)
168          throw new IllegalArgumentException JavaDoc("Attempt to remove lock ref with a null object");
169
170       HashMap JavaDoc mapInUse = getHashMap(id);
171
172       synchronized(mapInUse)
173       {
174           BeanLock lock = (BeanLock) mapInUse.get(id);
175
176           if (lock != null)
177           {
178              try
179              {
180                 lock.removeRef();
181                 if( trace )
182                    log.trace("Remove ref lock:"+lock);
183              }
184              finally
185              {
186                 // schrouf: ALLWAYS ensure proper map lock removal even in case
187
// of exception within lock.removeRef ! There seems to be a bug
188
// in the ref counting of QueuedPessimisticEJBLock under certain
189
// conditions ( lock.ref < 0 should never happen !!! )
190
if (lock.getRefs() <= 0)
191                 {
192                    Object JavaDoc mapLock = mapInUse.remove(lock.getId());
193                    if( trace )
194                       log.trace("Lock no longer referenced, lock: "+lock);
195                 }
196              }
197           }
198       }
199    }
200
201    public boolean canPassivate(Object JavaDoc id)
202    {
203       if (id == null)
204          throw new IllegalArgumentException JavaDoc("Attempt to passivate with a null object");
205
206       HashMap JavaDoc mapInUse = getHashMap(id);
207       synchronized (mapInUse)
208       {
209           BeanLock lock = (BeanLock) mapInUse.get(id);
210           if (lock == null)
211              throw new IllegalStateException JavaDoc("Attempt to passivate without a lock");
212
213           return (lock.getRefs() <= 1);
214       }
215    }
216
217    public void setLockCLass(Class JavaDoc lockClass)
218    {
219       this.lockClass = lockClass;
220    }
221
222    public void setReentrant(boolean reentrant)
223    {
224       this.reentrant = reentrant;
225    }
226
227    public void setContainer(Container container)
228    {
229       this.container = container;
230    }
231 }
232
Popular Tags