KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > perseus > concurrency > pessimistic > PessimisticConcurrencyManager


1 /**
2  * Copyright (C) 2001-2002
3  * - France Telecom R&D
4  * - Laboratoire Logiciels, Systemes, Reseaux - UMR 5526, CNRS-INPG-UJF
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  * Release: 1.0
21  *
22  * Authors:
23  *
24  */

25
26 package org.objectweb.perseus.concurrency.pessimistic;
27
28 import org.objectweb.perseus.concurrency.api.ConcurrencyException;
29 import org.objectweb.perseus.concurrency.api.ConcurrencyManager;
30 import org.objectweb.perseus.concurrency.lib.ReadWriteLockValue;
31 import org.objectweb.perseus.dependency.api.DependencyGraph;
32 import org.objectweb.fractal.api.control.BindingController;
33 import org.objectweb.fractal.api.control.IllegalBindingException;
34 import org.objectweb.fractal.api.control.LifeCycleController;
35 import org.objectweb.fractal.api.control.IllegalLifeCycleException;
36 import org.objectweb.fractal.api.NoSuchInterfaceException;
37 import org.objectweb.util.monolog.api.Logger;
38 import org.objectweb.util.monolog.api.BasicLevel;
39
40 import java.util.Collection JavaDoc;
41 import java.util.Map JavaDoc;
42 import java.util.HashMap JavaDoc;
43 import java.util.Iterator JavaDoc;
44
45 /**
46  * @author E. Bruneton
47  */

48 public abstract class PessimisticConcurrencyManager
49         implements ConcurrencyManager, BindingController,
50         PessimisticConcurrencyManagerAC, LifeCycleController {
51
52     public final static short POLICY_UNDEFINED = 0;
53     public final static short POLICY_MUTEX = 1;
54     public final static short POLICY_RW_PRIORITY2READERS = 2;
55     public final static short POLICY_RW_FIFO = 3;
56     public final static String JavaDoc[] policyStringVal = {
57         "POLICY_UNDEFINED",
58         "POLICY_MUTEX",
59         "POLICY_RW_PRIORITY2READERS",
60         "POLICY_RW_FIFO"
61     };
62     public final static String JavaDoc DEPENDENCY_GRAPH_BINDING = "dependency-graph";
63
64     private String JavaDoc state = LifeCycleController.STOPPED;
65
66     /**
67      * True to distinguish read/write locks, false to use a single lock for
68      * both modes.
69      */

70     private short policy = POLICY_RW_FIFO;
71     private final static short POLICY_LAST = POLICY_RW_FIFO;
72     /**
73      * A map associating locks to all oids in all active contexts.
74      */

75     protected Map JavaDoc locks;
76
77     protected DependencyGraph dg = null;
78
79     /**
80      * A map associating a ContextInfo to each context.
81      */

82     protected Map JavaDoc contextInfos;
83
84     protected Logger logger = null;
85     
86     protected boolean thinLockAllowed = true;
87
88     public PessimisticConcurrencyManager() throws ConcurrencyException {
89 // this(POLICY_RW_FIFO);
90
}
91
92     public PessimisticConcurrencyManager(short policy) throws ConcurrencyException {
93         //super();
94
}
95     
96     /**
97      * @param ctx is the context using the resource
98      * @param resourceId is the resource identifier
99      * @param lock is the lock instance matching the resource
100      * @param hints uses to give information on access
101      * @return the resource state to use
102      */

103     protected abstract Object JavaDoc getState(Object JavaDoc ctx,
104                                        Object JavaDoc resourceId,
105                                        Lock lock) throws ConcurrencyException;
106
107
108     //IMPLEMENTATION OF THE UserBindingControler INTERFACE //
109
//------------------------------------------------------//
110

111     public String JavaDoc[] listFc() {
112         return new String JavaDoc[] {DEPENDENCY_GRAPH_BINDING};
113     }
114
115     public Object JavaDoc lookupFc(String JavaDoc s) throws NoSuchInterfaceException {
116         if (DEPENDENCY_GRAPH_BINDING.equals(s)) {
117             return dg;
118         }
119 //FIXME: throw new NoSuchInterfaceException(s);
120
return null;
121     }
122
123     public void bindFc(String JavaDoc s, Object JavaDoc o) throws IllegalBindingException,
124             NoSuchInterfaceException {
125         try {
126             if ("logger".equals(s)) {
127                 logger = (Logger) o;
128             } else if (DEPENDENCY_GRAPH_BINDING.equals(s)) {
129                 if (dg != null) {
130                     throw new IllegalBindingException(s + ": Already bound");
131                 }
132                 dg = (DependencyGraph) o;
133             }
134         } catch (ClassCastException JavaDoc e) {
135             throw new IllegalBindingException(s + ":" + e.getMessage());
136         }
137 //FIXME: throw new NoSuchInterfaceException(s);
138
}
139
140     public void unbindFc(String JavaDoc s) throws NoSuchInterfaceException {
141         if (DEPENDENCY_GRAPH_BINDING.equals(s)) {
142             dg = null;
143         }
144 //FIXME: throw new NoSuchInterfaceException(s);
145
}
146
147     //IMPLEMENTATION OF THE ConcurrencyManager INTERFACE //
148
//---------------------------------------------------//
149
public String JavaDoc getFcState() {
150         return state;
151     }
152
153     public void startFc() throws IllegalLifeCycleException {
154         if (state == LifeCycleController.STARTED) return;
155         locks = new HashMap JavaDoc();
156         contextInfos = new HashMap JavaDoc();
157         state = LifeCycleController.STARTED;
158         switch (policy) {
159         case POLICY_MUTEX:
160             logger.log(BasicLevel.INFO, "Pessimistic Concurrency Manager runs with POLICY_MUTEX.");
161             break;
162         case POLICY_RW_PRIORITY2READERS:
163             logger.log(BasicLevel.INFO, "Pessimistic Concurrency Manager runs with POLICY_RW_PRIORITY2READERS.");
164             break;
165         case POLICY_RW_FIFO:
166             logger.log(BasicLevel.INFO, "Pessimistic Concurrency Manager runs with POLICY_RW_FIFO.");
167             break;
168         }
169     }
170
171     public void stopFc() throws IllegalLifeCycleException {
172         if (state == LifeCycleController.STOPPED) return;
173         contextInfos = null;
174         locks = null;
175         state = LifeCycleController.STOPPED;
176     }
177
178     //IMPLEMENTATION OF THE ConcurrencyManager INTERFACE //
179
//---------------------------------------------------//
180

181     public void begin(Object JavaDoc ctx) {
182         getContextInfo(ctx).rollback = false;
183     }
184
185     public boolean validate(Object JavaDoc ctx) {
186         ContextInfo info = (ContextInfo) contextInfos.get(ctx);
187         return info == null || !info.rollback;
188     }
189
190     public void finalize(Object JavaDoc ctx) {
191         freeLocks(ctx);
192     }
193     private void freeLocks(Object JavaDoc ctx) {
194         boolean debug = logger != null && logger.isLoggable(BasicLevel.DEBUG);
195         if (debug) {
196             logger.log(BasicLevel.DEBUG, "Finalize the context: " + ctx);
197         }
198         synchronized (locks) {
199             Iterator JavaDoc entries = locks.entrySet().iterator();
200             while (entries.hasNext()) {
201                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) entries.next();
202                 Lock lock = (Lock) entry.getValue();
203                 if (lock.close(ctx)) {
204                     closeLock(lock, ctx);
205                     entries.remove();
206                 }
207             }
208         }
209         contextInfos.remove(ctx);
210     }
211
212     public void closeLock(Lock lock, Object JavaDoc ctx) {
213     }
214     
215     public void abort(Object JavaDoc ctx) {
216         freeLocks(ctx);
217     }
218
219     protected Object JavaDoc getResourceId(Object JavaDoc object) {
220         return object;
221     }
222     
223     public Object JavaDoc readIntention(Object JavaDoc ctx, Object JavaDoc resource, Object JavaDoc thinLock)
224             throws ConcurrencyException {
225         Object JavaDoc resourceId = getResourceId(resource);
226         Lock lock = getLock(resourceId, null);
227         try {
228             lock.readIntention(ctx);
229         } catch (ConcurrencyException e) {
230             getContextInfo(ctx).rollback = true;
231             throw e;
232         }
233         return getState(ctx, resource, lock);
234     }
235
236     public Object JavaDoc writeIntention(Object JavaDoc ctx, Object JavaDoc resource, Object JavaDoc thinLock)
237             throws ConcurrencyException {
238         Object JavaDoc resourceId = getResourceId(resource);
239         if (thinLockAllowed && thinLock != null) {
240             // The application ask a thin lock on a resource. Firstly take
241
// the read lock on resource in order to avoid concurrent
242
// writers (resource lock vs thin lock)
243
Lock lock = getLock(resourceId, null);
244             try {
245                 lock.readIntention(ctx);
246             } catch (ConcurrencyException e) {
247                 getContextInfo(ctx).rollback = true;
248                 throw e;
249             }
250             if (lock.getMax() >= ReadWriteLockValue.UPGRADE) {
251                 // The lock has already been taken with write intention
252
// (upgrade or write) on the resource. Then a thin lock is
253
// useless.
254
return getState(ctx, resource, lock);
255             }
256             // The resouce lock level is not enough, then take the thin lock
257
if (thinLock instanceof Collection JavaDoc) {
258                 for(Iterator JavaDoc it = ((Collection JavaDoc) thinLock).iterator(); it.hasNext();) {
259                     lock = getLock(resourceId, it.next());
260                     try {
261                         lock.writeIntention(ctx);
262                     } catch (ConcurrencyException e) {
263                         getContextInfo(ctx).rollback = true;
264                         throw e;
265                     }
266                 }
267                 //As a read resource lock has been previously taken, pass only
268
// the last lock of the collection
269
return getState(ctx, resource, lock);
270             }
271         }
272         Lock lock = getLock(resourceId, (thinLockAllowed ? thinLock : null));
273         try {
274             lock.writeIntention(ctx);
275         } catch (ConcurrencyException e) {
276             getContextInfo(ctx).rollback = true;
277             throw e;
278         }
279         return getState(ctx, resource, lock);
280     }
281
282     //OTHER METHODS //
283
//--------------//
284
private static class OID {
285         public Object JavaDoc oid;
286         public Object JavaDoc lockHints;
287         public OID(Object JavaDoc _oid, Object JavaDoc _lockHints) {
288             this.oid = _oid;
289             this.lockHints = _lockHints;
290             
291         }
292         public boolean equals(Object JavaDoc o) {
293             return o instanceof OID
294             && ((OID) o).oid.equals(oid)
295             && ((OID) o).lockHints.equals(lockHints);
296         }
297     }
298     /**
299      * Returns the lock associated to the given oid.
300      * @param oid an object identifier.
301      * @return the lock associated to the given oid.
302      */

303     protected Lock getLock(Object JavaDoc oid, Object JavaDoc hints) {
304         if (thinLockAllowed && hints != null) {
305             oid = new OID(oid, hints);
306         }
307         synchronized (locks) {
308             Lock lock = (Lock) locks.get(oid);
309             if (lock == null) {
310                 switch (policy) {
311                 case POLICY_MUTEX:
312                     lock = new MutexLock(hints, dg);
313                     break;
314                 case POLICY_RW_PRIORITY2READERS:
315                     lock = new RWPri2RLock(hints, dg);
316                     break;
317                 case POLICY_RW_FIFO:
318                     lock = new RWFifoLock(hints, dg);
319                     break;
320                 }
321                 lock.oid = oid;
322                 locks.put(oid, lock);
323                 if (logger != null) {
324                     lock.logger = logger;
325                     if (logger.isLoggable(BasicLevel.DEBUG)) {
326                         logger.log(BasicLevel.DEBUG, "Allocate a Lock for the oid: " + oid);
327                     }
328                 }
329             }
330             lock.reserve();
331             return lock;
332         }
333     }
334
335     protected ContextInfo getContextInfo(Object JavaDoc ctxt) {
336         ContextInfo info = (ContextInfo) contextInfos.get(ctxt);
337         if (info == null) {
338             info = new ContextInfo();
339             contextInfos.put(ctxt, info);
340         }
341         return info;
342     }
343
344     public String JavaDoc getPolicy() {
345         return policyStringVal[policy];
346     }
347
348     public void setPolicy(String JavaDoc policy) throws IllegalLifeCycleException {
349         if (!LifeCycleController.STOPPED.equals(state)) {
350             throw new IllegalLifeCycleException("Cannot change lock policy of started pessimistic component");
351         }
352         for (short p = 0; p <= POLICY_LAST; p++) {
353             if (policyStringVal[p].equals(policy)) {
354                 this.policy = p;
355                 return;
356             }
357         }
358         throw new IllegalArgumentException JavaDoc("unrecognized locking policy: " + policy);
359     }
360
361     public boolean getThinkLockAllowed() {
362         return thinLockAllowed;
363     }
364     
365     public void setThinkLockAllowed(boolean val) {
366         thinLockAllowed = val;
367     }
368
369
370     /**
371      * Information associated to a context
372      */

373     protected static class ContextInfo {
374         // long date; // date of begin()
375
public boolean rollback; // if the validate() method must return false
376
}
377 }
378
Popular Tags