blob: d96fcc21126f20937f1586af1daa95681c683eb6 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1998-2005 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24/*
25 */
26
27import java.rmi.*;
28import sun.rmi.transport.*;
29import sun.rmi.*;
30import java.io.*;
31import java.lang.reflect.*;
32import java.rmi.dgc.*;
33import java.util.*;
34import java.rmi.registry.*;
35import java.rmi.server.*;
36
37public class TestImpl extends UnicastRemoteObject
38 implements Test {
39
40 static Thread locker = null;
41 static TestImpl foo = null;
42 static TestImpl bar = null;
43
44 TestImpl() throws RemoteException {
45 }
46
47 public String echo(String msg) throws RemoteException {
48
49 if (locker == null) {
50 // hold the target if not already held
51 locker = lockTargetExpireLeases(foo, DGCDeadLock.HOLD_TARGET_TIME);
52 }
53 return "Message received: " + msg;
54 }
55
56 static public void main(String[] args) {
57 Registry registry = null;
58
59 try {
60 registry = java.rmi.registry.LocateRegistry.
61 createRegistry(TestLibrary.REGISTRY_PORT);
62
63 //export "Foo"
64 foo = new TestImpl();
65 Naming.rebind("rmi://:" +
66 TestLibrary.REGISTRY_PORT
67 + "/Foo", foo);
68
69 try {
70 //export "Bar" after leases have been expired.
71 bar = new TestImpl();
72 Naming.rebind("rmi://localhost:" +
73 TestLibrary.REGISTRY_PORT
74 + "/Bar", bar);
75 } catch (Exception e) {
76 throw new RemoteException(e.getMessage());
77 }
78 Thread.sleep(DGCDeadLock.TEST_FAIL_TIME);
79 System.err.println("object vm exiting...");
80 System.exit(0);
81
82 } catch (Exception e) {
83 System.err.println(e.getMessage());
84 e.printStackTrace();
85 } finally {
86 TestLibrary.unexport(registry);
87 registry = null;
88 }
89 }
90
91 static Thread lockTargetExpireLeases(Remote toLock, int timeOut) {
92 Thread t = new Thread((Runnable) new TargetLocker(toLock, timeOut));
93 t.start();
94 return t;
95 }
96
97 static class TargetLocker implements Runnable {
98
99 Remote toLock = null;
100 int timeOut = 0;
101
102 TargetLocker(Remote toLock, int timeOut) {
103 this.toLock = toLock;
104 this.timeOut = timeOut;
105 }
106
107 public void run() {
108 try {
109 // give dgc dirty calls time to finish.
110 Thread.currentThread().sleep(4000);
111
112 java.security.AccessController.
113 doPrivileged(new LockTargetCheckLeases(toLock,
114 timeOut));
115
116 } catch (Exception e) {
117 System.err.println(e.getMessage());
118 e.printStackTrace();
119 System.exit(1);
120 }
121 }
122 }
123
124 static class LockTargetCheckLeases
125 implements java.security.PrivilegedAction {
126
127 Remote toLock = null;
128 int timeOut = 0;
129
130 LockTargetCheckLeases(Remote toLock, int timeOut) {
131 this.toLock = toLock;
132 this.timeOut = timeOut;
133 }
134
135 public Object run() {
136 try {
137
138 Class args[] = new Class[1];
139
140 Class objTableClass = Class.forName
141 ("sun.rmi.transport.ObjectTable");
142
143 /* get the Target that corresponds to toLock from the
144 * ObjectTable
145 */
146 args[0] = Class.forName("java.rmi.Remote");
147 Method objTableGetTarget =
148 objTableClass.getDeclaredMethod("getTarget", args );
149 objTableGetTarget.setAccessible(true);
150
151 Target lockTarget =
152 ((Target) objTableGetTarget.invoke
153 (null , new Object [] {toLock} ));
154
155 // make sure the lease on this object has expired.
156 expireLeases(lockTarget);
157
158 // stop other threads from using the target for toLock.
159 synchronized (lockTarget) {
160 System.err.println("Locked the relevant target, sleeping " +
161 timeOut/1000 + " seconds");
162 Thread.currentThread().sleep(timeOut);
163 System.err.println("Target unlocked");
164 }
165
166 } catch (Exception e) {
167 System.err.println(e.getMessage());
168 e.printStackTrace();
169 System.exit(1);
170 }
171 return null;
172 }
173 }
174
175 /* leases have long values, so no dirty calls which would lock out
176 * a clean call, but the leases need to expire anyway, so we do it
177 * explicitly.
178 */
179 static void expireLeases(Target t) throws Exception {
180
181 final Target target = t;
182
183 java.security.AccessController.doPrivileged(
184
185 // put this into another class?
186 new java.security.PrivilegedAction() {
187 public Object run() {
188 try {
189
190 Class DGCClass = Class.forName("sun.rmi.transport.DGCImpl");
191 Method getDGCImpl =
192 DGCClass.getDeclaredMethod("getDGCImpl", null );
193 getDGCImpl.setAccessible(true);
194
195 // make sure the lease on this object has expired.
196 DGC dgcImpl = ((DGC) getDGCImpl.invoke(null, null));
197
198 /* Get the lease table from the DGCImpl. */
199 Field reflectedLeaseTable =
200 dgcImpl.getClass().getDeclaredField("leaseTable");
201 reflectedLeaseTable.setAccessible(true);
202
203 Map leaseTable = (Map) reflectedLeaseTable.get(dgcImpl);
204
205 // dont really need this synchronization...
206 synchronized (leaseTable) {
207 Iterator en = leaseTable.values().iterator();
208 while (en.hasNext()) {
209 Object info = en.next();
210
211 /* Get the notifySet in the leaseInfo object. */
212 Field notifySetField =
213 info.getClass().getDeclaredField("notifySet");
214 notifySetField.setAccessible(true);
215 HashSet notifySet = (HashSet) notifySetField.get(info);
216
217 Iterator iter = notifySet.iterator();
218 while (iter.hasNext()) {
219 Target notified = (Target) iter.next();
220
221 if (notified == target) {
222
223 /* Get and set the expiration field from the info object. */
224 Field expirationField = info.getClass().
225 getDeclaredField("expiration");
226 expirationField.setAccessible(true);
227 expirationField.setLong(info, 0);
228 }
229 }
230 }
231 }
232 } catch (Exception e) {
233 System.err.println(e.getMessage());
234 e.printStackTrace();
235 System.exit(1);
236 }
237 // no interesting return value for this privileged action
238 return null;
239 }
240 });
241 }
242}