1 |
| |
2 |
| |
3 |
| |
4 |
| |
5 |
| |
6 |
| |
7 |
| package org.jboss.cache.transaction; |
8 |
| |
9 |
| import junit.framework.TestCase; |
10 |
| import org.jboss.cache.CacheException; |
11 |
| import org.jboss.cache.CacheImpl; |
12 |
| import org.jboss.cache.interceptors.OrderedSynchronizationHandler; |
13 |
| import org.jboss.cache.misc.TestingUtil; |
14 |
| import org.jboss.cache.transaction.NotifyingTransactionManager.Notification; |
15 |
| import org.jgroups.Channel; |
16 |
| import org.jgroups.JChannel; |
17 |
| |
18 |
| import javax.transaction.RollbackException; |
19 |
| import javax.transaction.Synchronization; |
20 |
| import javax.transaction.SystemException; |
21 |
| import javax.transaction.Transaction; |
22 |
| import javax.transaction.TransactionManager; |
23 |
| |
24 |
| |
25 |
| |
26 |
| |
27 |
| public class AbortionTest extends TestCase |
28 |
| { |
29 |
| private MyTC cache1, cache2, cache3; |
30 |
| |
31 |
3
| protected void setUp() throws Exception
|
32 |
| { |
33 |
3
| super.setUp();
|
34 |
3
| System.out.println("********* START: SET UP *************");
|
35 |
3
| cache1 = initCache(false);
|
36 |
3
| TestingUtil.sleepThread(1500);
|
37 |
3
| cache2 = initCache(false);
|
38 |
3
| cache3 = initCache(true);
|
39 |
3
| System.out.println("********* END: SET UP *************");
|
40 |
| } |
41 |
| |
42 |
| |
43 |
3
| protected void tearDown() throws Exception
|
44 |
| { |
45 |
3
| System.out.println("********* START: TEAR DOWN *************");
|
46 |
3
| destroyCache(cache3);
|
47 |
3
| destroyCache(cache2);
|
48 |
3
| destroyCache(cache1);
|
49 |
3
| cache1 = null;
|
50 |
3
| cache2 = null;
|
51 |
3
| cache3 = null;
|
52 |
3
| super.tearDown();
|
53 |
3
| System.out.println("********* END: TEAR DOWN *************");
|
54 |
| } |
55 |
| |
56 |
9
| private MyTC initCache(boolean notifying) throws Exception
|
57 |
| { |
58 |
9
| MyTC c = new MyTC();
|
59 |
9
| c.getConfiguration().setCacheMode("REPL_SYNC");
|
60 |
9
| c.getConfiguration().setClusterConfig(getJGroupsStack());
|
61 |
9
| c.getConfiguration().setFetchInMemoryState(false);
|
62 |
9
| if (!notifying)
|
63 |
| { |
64 |
6
| c.getConfiguration().setTransactionManagerLookupClass("org.jboss.cache.transaction.DummyTransactionManagerLookup");
|
65 |
| } |
66 |
| else |
67 |
| { |
68 |
3
| c.getConfiguration().setTransactionManagerLookupClass("org.jboss.cache.transaction.NotifyingTransactionManager");
|
69 |
| } |
70 |
9
| c.start();
|
71 |
9
| return c;
|
72 |
| } |
73 |
| |
74 |
| |
75 |
9
| private String getJGroupsStack()
|
76 |
| { |
77 |
| |
78 |
| |
79 |
| |
80 |
| |
81 |
| |
82 |
| |
83 |
| |
84 |
| |
85 |
| |
86 |
9
| return JChannel.DEFAULT_PROTOCOL_STACK;
|
87 |
| } |
88 |
| |
89 |
9
| private void destroyCache(MyTC c)
|
90 |
| { |
91 |
9
| if (c != null)
|
92 |
| { |
93 |
9
| c.stop();
|
94 |
9
| c.destroy();
|
95 |
| } |
96 |
| } |
97 |
| |
98 |
1
| public void testSyncCaches() throws Exception
|
99 |
| { |
100 |
1
| performTest(false, false);
|
101 |
| } |
102 |
| |
103 |
1
| public void testSyncCachesSyncCommitRollback() throws Exception
|
104 |
| { |
105 |
1
| performTest(true, false);
|
106 |
| } |
107 |
| |
108 |
| |
109 |
| |
110 |
| |
111 |
| |
112 |
| |
113 |
1
| public void testAbortBeforeCompletion() throws Exception
|
114 |
| { |
115 |
1
| performTest(true, true);
|
116 |
| } |
117 |
| |
118 |
3
| private void performTest(boolean syncCommitRollback, boolean abortBeforeCompletion) throws Exception
|
119 |
| { |
120 |
3
| cache1.getConfiguration().setSyncCommitPhase(syncCommitRollback);
|
121 |
3
| cache1.getConfiguration().setSyncRollbackPhase(syncCommitRollback);
|
122 |
3
| cache2.getConfiguration().setSyncCommitPhase(syncCommitRollback);
|
123 |
3
| cache2.getConfiguration().setSyncRollbackPhase(syncCommitRollback);
|
124 |
3
| cache3.getConfiguration().setSyncCommitPhase(syncCommitRollback);
|
125 |
3
| cache3.getConfiguration().setSyncRollbackPhase(syncCommitRollback);
|
126 |
| |
127 |
3
| TransactionManager mgr1 = cache1.getTransactionManager();
|
128 |
3
| TransactionManager mgr2 = cache2.getTransactionManager();
|
129 |
3
| assertTrue(cache3.getTransactionManager() instanceof NotifyingTransactionManager);
|
130 |
3
| NotifyingTransactionManager mgr3 = (NotifyingTransactionManager) cache3.getTransactionManager();
|
131 |
| |
132 |
3
| assertSame(mgr1, mgr2);
|
133 |
3
| assertNotSame(mgr1, mgr3);
|
134 |
3
| assertNotSame(mgr2, mgr3);
|
135 |
| |
136 |
3
| assertTrue(mgr1 instanceof DummyTransactionManager);
|
137 |
3
| assertTrue(mgr2 instanceof DummyTransactionManager);
|
138 |
| |
139 |
3
| cache1.put("/test", "key", "value");
|
140 |
| |
141 |
3
| assertEquals("value", cache1.get("/test", "key"));
|
142 |
3
| assertEquals("value", cache2.get("/test", "key"));
|
143 |
3
| assertEquals("value", cache3.get("/test", "key"));
|
144 |
| |
145 |
3
| mgr3.setNotification(new TestNotification(abortBeforeCompletion));
|
146 |
| |
147 |
3
| mgr1.begin();
|
148 |
3
| Transaction tx = mgr1.getTransaction();
|
149 |
3
| cache1.put("/test", "key", "value2");
|
150 |
3
| tx.commit();
|
151 |
| |
152 |
3
| TestingUtil.sleepThread(5000);
|
153 |
| |
154 |
| |
155 |
3
| assertEquals(0, cache1.getNumberOfLocksHeld());
|
156 |
3
| assertEquals(0, cache2.getNumberOfLocksHeld());
|
157 |
3
| assertEquals("put in transaction should NOT have been rolled back", "value2", cache1.get("/test", "key"));
|
158 |
3
| assertEquals("put in transaction should NOT have been rolled back", "value2", cache2.get("/test", "key"));
|
159 |
| |
160 |
| } |
161 |
| |
162 |
| |
163 |
| class TestNotification implements Notification |
164 |
| { |
165 |
| boolean abortBeforeCompletion; |
166 |
| |
167 |
3
| public TestNotification(boolean abortBeforeCompletion)
|
168 |
| { |
169 |
3
| this.abortBeforeCompletion = abortBeforeCompletion;
|
170 |
| } |
171 |
| |
172 |
3
| public void notify(Transaction tx) throws SystemException, RollbackException
|
173 |
| { |
174 |
3
| final Transaction finalTx = tx;
|
175 |
3
| System.out.println("Notify called.");
|
176 |
| |
177 |
3
| Synchronization abort = new Synchronization()
|
178 |
| { |
179 |
| |
180 |
3
| public void beforeCompletion()
|
181 |
| { |
182 |
3
| if (abortBeforeCompletion)
|
183 |
| { |
184 |
1
| cache3.myChannel.close();
|
185 |
1
| System.out.println("Returning from abort.beforeCompletion");
|
186 |
1
| try
|
187 |
| { |
188 |
1
| finalTx.setRollbackOnly();
|
189 |
| } |
190 |
| catch (SystemException e) |
191 |
| { |
192 |
0
| throw new RuntimeException("Unable to set rollback", e);
|
193 |
| } |
194 |
1
| throw new RuntimeException("Dummy exception");
|
195 |
| } |
196 |
| } |
197 |
| |
198 |
3
| public void afterCompletion(int i)
|
199 |
| { |
200 |
3
| if (!abortBeforeCompletion)
|
201 |
| { |
202 |
2
| cache3.myChannel.close();
|
203 |
2
| System.out.println("Returning from abort.afterCompletion");
|
204 |
2
| throw new RuntimeException("Dummy exception");
|
205 |
| } |
206 |
| } |
207 |
| }; |
208 |
| |
209 |
3
| OrderedSynchronizationHandler osh = OrderedSynchronizationHandler.getInstance(tx);
|
210 |
3
| osh.registerAtHead(abort);
|
211 |
3
| System.out.println("Added sync handler.");
|
212 |
| } |
213 |
| |
214 |
| } |
215 |
| |
216 |
| ; |
217 |
| |
218 |
| |
219 |
| public static class MyTC extends CacheImpl |
220 |
| { |
221 |
| Channel myChannel; |
222 |
| |
223 |
9
| public MyTC() throws Exception
|
224 |
| { |
225 |
9
| super();
|
226 |
| } |
227 |
| |
228 |
9
| public void start() throws CacheException
|
229 |
| { |
230 |
9
| super.start();
|
231 |
9
| myChannel = channel;
|
232 |
| } |
233 |
| } |
234 |
| |
235 |
| } |