1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.transaction.memory;
19
20 import java.util.Collection;
21 import java.util.Map;
22 import java.util.Set;
23
24 import org.apache.commons.transaction.locking.ReadWriteLockManager;
25 import org.apache.commons.transaction.util.LoggerFacade;
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 public class PessimisticMapWrapper extends TransactionalMapWrapper {
46
47 protected static final int READ = 1;
48 protected static final int WRITE = 2;
49
50 protected static final Object GLOBAL_LOCK = "GLOBAL";
51
52 protected ReadWriteLockManager lockManager;
53
54 protected long readTimeOut = 60000;
55
56
57
58
59
60
61
62
63
64 public PessimisticMapWrapper(Map wrapped, LoggerFacade logger) {
65 this(wrapped, new HashMapFactory(), new HashSetFactory(), logger);
66 }
67
68
69
70
71
72
73
74
75
76
77
78 public PessimisticMapWrapper(Map wrapped, MapFactory mapFactory, SetFactory setFactory, LoggerFacade logger) {
79 super(wrapped, mapFactory, setFactory);
80 lockManager = new ReadWriteLockManager(logger, readTimeOut);
81
82 }
83
84 public void startTransaction() {
85 if (getActiveTx() != null) {
86 throw new IllegalStateException(
87 "Active thread " + Thread.currentThread() + " already associated with a transaction!");
88 }
89 LockingTxContext context = new LockingTxContext();
90 setActiveTx(context);
91 }
92
93 public Collection values() {
94 assureGlobalReadLock();
95 return super.values();
96 }
97
98 public Set entrySet() {
99 assureGlobalReadLock();
100 return super.entrySet();
101 }
102
103 public Set keySet() {
104 assureGlobalReadLock();
105 return super.keySet();
106 }
107
108 public Object remove(Object key) {
109
110
111 assureWriteLock(key);
112 return super.remove(key);
113 }
114
115 public Object put(Object key, Object value) {
116
117
118 assureWriteLock(key);
119 return super.put(key, value);
120 }
121
122 protected void assureWriteLock(Object key) {
123 LockingTxContext txContext = (LockingTxContext) getActiveTx();
124 if (txContext != null) {
125 lockManager.writeLock(txContext, key);
126
127 lockManager.readLock(txContext, GLOBAL_LOCK);
128 }
129 }
130
131 protected void assureGlobalReadLock() {
132 LockingTxContext txContext = (LockingTxContext) getActiveTx();
133 if (txContext != null) {
134
135 lockManager.readLock(txContext, GLOBAL_LOCK);
136 }
137 }
138
139 public class LockingTxContext extends TxContext {
140
141 protected Set keys() {
142 lockManager.readLock(this, GLOBAL_LOCK);
143 return super.keys();
144 }
145
146 protected Object get(Object key) {
147 lockManager.readLock(this, key);
148
149 lockManager.readLock(this, GLOBAL_LOCK);
150 return super.get(key);
151 }
152
153 protected void put(Object key, Object value) {
154 lockManager.writeLock(this, key);
155
156 lockManager.readLock(this, GLOBAL_LOCK);
157 super.put(key, value);
158 }
159
160 protected void remove(Object key) {
161 lockManager.writeLock(this, key);
162
163 lockManager.readLock(this, GLOBAL_LOCK);
164 super.remove(key);
165 }
166
167 protected int size() {
168
169 lockManager.readLock(this, GLOBAL_LOCK);
170 return super.size();
171 }
172
173 protected void clear() {
174 lockManager.writeLock(this, GLOBAL_LOCK);
175 super.clear();
176 }
177
178 protected void dispose() {
179 super.dispose();
180 lockManager.releaseAll(this);
181 }
182
183 protected void finalize() throws Throwable {
184 dispose();
185 super.finalize();
186 }
187 }
188
189 }