KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > transaction > memory > PessimisticMapWrapper


1 /*
2  * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//transaction/src/java/org/apache/commons/transaction/memory/PessimisticMapWrapper.java,v 1.2 2004/12/14 12:12:46 ozeigermann Exp $
3  * $Revision$
4  * $Date: 2005-02-26 14:16:14 +0100 (Sa, 26 Feb 2005) $
5  *
6  * ====================================================================
7  *
8  * Copyright 1999-2002 The Apache Software Foundation
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */

23
24 package org.apache.commons.transaction.memory;
25
26 import java.util.Collection JavaDoc;
27 import java.util.Map JavaDoc;
28 import java.util.Set JavaDoc;
29
30 import org.apache.commons.transaction.locking.ReadWriteLockManager;
31 import org.apache.commons.transaction.util.LoggerFacade;
32
33 /**
34  * Wrapper that adds transactional control to all kinds of maps that implement the {@link Map} interface. By using
35  * pessimistic transaction control (blocking locks) this wrapper has better isolation than {@link TransactionalMapWrapper}, but
36  * also has less possible concurrency and may even deadlock. A commit, however, will never fail.
37  * <br>
38  * Start a transaction by calling {@link #startTransaction()}. Then perform the normal actions on the map and
39  * finally either call {@link #commitTransaction()} to make your changes permanent or {@link #rollbackTransaction()} to
40  * undo them.
41  * <br>
42  * <em>Caution:</em> Do not modify values retrieved by {@link #get(Object)} as this will circumvent the transactional mechanism.
43  * Rather clone the value or copy it in a way you see fit and store it back using {@link #put(Object, Object)}.
44  * <br>
45  * <em>Note:</em> This wrapper guarantees isolation level <code>SERIALIZABLE</code>.
46  *
47  * @version $Revision$
48  * @see TransactionalMapWrapper
49  * @see OptimisticMapWrapper
50  */

51 public class PessimisticMapWrapper extends TransactionalMapWrapper {
52
53     protected static final int READ = 1;
54     protected static final int WRITE = 2;
55
56     protected static final Object JavaDoc GLOBAL_LOCK = "GLOBAL";
57
58     protected ReadWriteLockManager lockManager;
59 // protected MultiLevelLock globalLock;
60
protected long readTimeOut = 60000; /* FIXME: pass in ctor */
61
62     /**
63      * Creates a new pessimistic transactional map wrapper. Temporary maps and sets to store transactional
64      * data will be instances of {@link java.util.HashMap} and {@link java.util.HashSet}.
65      *
66      * @param wrapped map to be wrapped
67      * @param logger
68      * generic logger used for all kinds of logging
69      */

70     public PessimisticMapWrapper(Map JavaDoc wrapped, LoggerFacade logger) {
71         this(wrapped, new HashMapFactory(), new HashSetFactory(), logger);
72     }
73
74     /**
75      * Creates a new pessimistic transactional map wrapper. Temporary maps and sets to store transactional
76      * data will be created and disposed using {@link MapFactory} and {@link SetFactory}.
77      *
78      * @param wrapped map to be wrapped
79      * @param mapFactory factory for temporary maps
80      * @param setFactory factory for temporary sets
81      * @param logger
82      * generic logger used for all kinds of logging
83      */

84     public PessimisticMapWrapper(Map JavaDoc wrapped, MapFactory mapFactory, SetFactory setFactory, LoggerFacade logger) {
85         super(wrapped, mapFactory, setFactory);
86         lockManager = new ReadWriteLockManager(logger, readTimeOut);
87 // globalLock = new GenericLock(GLOBAL_LOCK_NAME, WRITE, logger);
88
}
89
90     public void startTransaction() {
91         if (getActiveTx() != null) {
92             throw new IllegalStateException JavaDoc(
93                 "Active thread " + Thread.currentThread() + " already associated with a transaction!");
94         }
95         LockingTxContext context = new LockingTxContext();
96         setActiveTx(context);
97     }
98
99     public Collection JavaDoc values() {
100         assureGlobalReadLock();
101         return super.values();
102     }
103
104     public Set JavaDoc entrySet() {
105         assureGlobalReadLock();
106         return super.entrySet();
107     }
108
109     public Set JavaDoc keySet() {
110         assureGlobalReadLock();
111         return super.keySet();
112     }
113
114     public Object JavaDoc remove(Object JavaDoc key) {
115         // assure we get a write lock before super can get a read lock to avoid lots
116
// of deadlocks
117
assureWriteLock(key);
118         return super.remove(key);
119     }
120
121     public Object JavaDoc put(Object JavaDoc key, Object JavaDoc value) {
122         // assure we get a write lock before super can get a read lock to avoid lots
123
// of deadlocks
124
assureWriteLock(key);
125         return super.put(key, value);
126     }
127
128     protected void assureWriteLock(Object JavaDoc key) {
129         LockingTxContext txContext = (LockingTxContext) getActiveTx();
130         if (txContext != null) {
131             lockManager.writeLock(txContext, key);
132             // XXX fake intention lock (prohibits global WRITE)
133
lockManager.readLock(txContext, GLOBAL_LOCK);
134         }
135     }
136     
137     protected void assureGlobalReadLock() {
138         LockingTxContext txContext = (LockingTxContext) getActiveTx();
139         if (txContext != null) {
140             // XXX fake intention lock (prohibits global WRITE)
141
lockManager.readLock(txContext, GLOBAL_LOCK);
142         }
143     }
144     
145     public class LockingTxContext extends TxContext {
146
147         protected Set JavaDoc keys() {
148             lockManager.readLock(this, GLOBAL_LOCK);
149             return super.keys();
150         }
151
152         protected Object JavaDoc get(Object JavaDoc key) {
153             lockManager.readLock(this, key);
154             // XXX fake intention lock (prohibits global WRITE)
155
lockManager.readLock(this, GLOBAL_LOCK);
156             return super.get(key);
157         }
158
159         protected void put(Object JavaDoc key, Object JavaDoc value) {
160             lockManager.writeLock(this, key);
161             // XXX fake intention lock (prohibits global WRITE)
162
lockManager.readLock(this, GLOBAL_LOCK);
163             super.put(key, value);
164         }
165
166         protected void remove(Object JavaDoc key) {
167             lockManager.writeLock(this, key);
168             // XXX fake intention lock (prohibits global WRITE)
169
lockManager.readLock(this, GLOBAL_LOCK);
170             super.remove(key);
171         }
172
173         protected int size() {
174             // XXX this is bad luck, we need a global read lock just for the size :( :( :(
175
lockManager.readLock(this, GLOBAL_LOCK);
176             return super.size();
177         }
178
179         protected void clear() {
180             lockManager.writeLock(this, GLOBAL_LOCK);
181             super.clear();
182         }
183
184         protected void dispose() {
185             super.dispose();
186             lockManager.releaseAll(this);
187         }
188
189         protected void finalize() throws Throwable JavaDoc {
190             dispose();
191             super.finalize();
192         }
193     }
194
195 }
196
Popular Tags