53 |
53 |
54 /** |
54 /** |
55 * Return this object. The need for this method is explained below. |
55 * Return this object. The need for this method is explained below. |
56 */ |
56 */ |
57 public Self getSelf() { |
57 public Self getSelf() { |
58 return this; |
58 return this; |
59 } |
59 } |
60 |
60 |
61 public void unreferenced() { |
61 public void unreferenced() { |
62 synchronized (this) { |
62 synchronized (this) { |
63 unreferenced = true; |
63 unreferenced = true; |
64 notifyAll(); |
64 notifyAll(); |
65 } |
65 } |
66 } |
66 } |
67 |
67 |
68 public static void main(String[] args) { |
68 public static void main(String[] args) { |
69 |
69 |
70 System.err.println("\nRegression test for bug 4268258\n"); |
70 System.err.println("\nRegression test for bug 4268258\n"); |
71 |
71 |
72 /* |
72 /* |
73 * Set properties to tweak DGC behavior so that this test will execute |
73 * Set properties to tweak DGC behavior so that this test will execute |
74 * quickly: set the granted lease duration to 10 seconds, the interval |
74 * quickly: set the granted lease duration to 10 seconds, the interval |
75 * that leases are checked to 3 seconds. |
75 * that leases are checked to 3 seconds. |
76 */ |
76 */ |
77 System.setProperty("java.rmi.dgc.leaseValue", "10000"); |
77 System.setProperty("java.rmi.dgc.leaseValue", "10000"); |
78 System.setProperty("sun.rmi.dgc.checkInterval", "3000"); |
78 System.setProperty("sun.rmi.dgc.checkInterval", "3000"); |
79 |
79 |
80 /* |
80 /* |
81 * Make idle connections time out almost instantly (0.1 seconds) so |
81 * Make idle connections time out almost instantly (0.1 seconds) so |
82 * that the DGC implementation will have to make a new connection for |
82 * that the DGC implementation will have to make a new connection for |
83 * each dirty call, thus going through the socket factory, where we |
83 * each dirty call, thus going through the socket factory, where we |
84 * can easily cause the operation to fail. |
84 * can easily cause the operation to fail. |
85 */ |
85 */ |
86 System.setProperty("sun.rmi.transport.connectionTimeout", "100"); |
86 System.setProperty("sun.rmi.transport.connectionTimeout", "100"); |
87 |
87 |
88 RetryDirtyCalls impl = new RetryDirtyCalls(); |
88 RetryDirtyCalls impl = new RetryDirtyCalls(); |
89 |
89 |
90 try { |
90 try { |
91 TestSF sf = new TestSF(); |
91 TestSF sf = new TestSF(); |
92 RMISocketFactory.setSocketFactory(sf); |
92 RMISocketFactory.setSocketFactory(sf); |
93 |
93 |
94 /* |
94 /* |
95 * The stub returned by UnicastRemoteObject.exportObject() does |
95 * The stub returned by UnicastRemoteObject.exportObject() does |
96 * not participate in DGC, but it does allow us to invoke a method |
96 * not participate in DGC, but it does allow us to invoke a method |
97 * on the remote object through RMI. Therefore, we invoke the |
97 * on the remote object through RMI. Therefore, we invoke the |
98 * getSelf() method through RMI, which returns an equivalent stub |
98 * getSelf() method through RMI, which returns an equivalent stub |
99 * that does participate in DGC. |
99 * that does participate in DGC. |
100 */ |
100 */ |
101 Self stub = (Self) UnicastRemoteObject.exportObject(impl); |
101 Self stub = (Self) UnicastRemoteObject.exportObject(impl); |
102 Self dgcStub = stub.getSelf(); |
102 Self dgcStub = stub.getSelf(); |
103 stub = null; // in case 4114579 has been fixed |
103 stub = null; // in case 4114579 has been fixed |
104 |
104 |
105 /* |
105 /* |
106 * Set the socket factory to cause 3 connections attempts in a row |
106 * Set the socket factory to cause 3 connections attempts in a row |
107 * to fail before allowing a connection to succeed, expecting the |
107 * to fail before allowing a connection to succeed, expecting the |
108 * client-side DGC implementation to make at least four attempts. |
108 * client-side DGC implementation to make at least four attempts. |
109 */ |
109 */ |
110 final int FLAKE_FACTOR = 3; |
110 final int FLAKE_FACTOR = 3; |
111 sf.setFlakeFactor(FLAKE_FACTOR); |
111 sf.setFlakeFactor(FLAKE_FACTOR); |
112 |
112 |
113 long deadline = System.currentTimeMillis() + TIMEOUT; |
113 long deadline = System.currentTimeMillis() + TIMEOUT; |
114 boolean unreferenced; |
114 boolean unreferenced; |
115 |
115 |
116 synchronized (impl) { |
116 synchronized (impl) { |
117 while (!(unreferenced = impl.unreferenced)) { |
117 while (!(unreferenced = impl.unreferenced)) { |
118 long timeToWait = deadline - System.currentTimeMillis(); |
118 long timeToWait = deadline - System.currentTimeMillis(); |
119 if (timeToWait > 0) { |
119 if (timeToWait > 0) { |
120 impl.wait(timeToWait); |
120 impl.wait(timeToWait); |
121 } else { |
121 } else { |
122 break; |
122 break; |
123 } |
123 } |
124 } |
124 } |
125 } |
125 } |
126 |
126 |
127 if (unreferenced) { |
127 if (unreferenced) { |
128 throw new RuntimeException("remote object unreferenced"); |
128 throw new RuntimeException("remote object unreferenced"); |
129 } |
129 } |
130 |
130 |
131 int createCount = sf.getCreateCount(); |
131 int createCount = sf.getCreateCount(); |
132 if (createCount == 0) { |
132 if (createCount == 0) { |
133 throw new RuntimeException("test socket factory never used"); |
133 throw new RuntimeException("test socket factory never used"); |
134 } else if (createCount < (FLAKE_FACTOR + 3)) { |
134 } else if (createCount < (FLAKE_FACTOR + 3)) { |
135 /* |
135 /* |
136 * The unreferenced method was not invoked for some reason, |
136 * The unreferenced method was not invoked for some reason, |
137 * but the dirty calls were clearly not retried well enough. |
137 * but the dirty calls were clearly not retried well enough. |
138 */ |
138 */ |
139 throw new RuntimeException( |
139 throw new RuntimeException( |
140 "test failed because dirty calls not retried enough, " + |
140 "test failed because dirty calls not retried enough, " + |
141 "but remote object not unreferenced"); |
141 "but remote object not unreferenced"); |
142 } |
142 } |
143 |
143 |
144 System.err.println( |
144 System.err.println( |
145 "TEST PASSED: remote object not unreferenced"); |
145 "TEST PASSED: remote object not unreferenced"); |
146 |
146 |
147 } catch (Exception e) { |
147 } catch (Exception e) { |
148 e.printStackTrace(); |
148 e.printStackTrace(); |
149 throw new RuntimeException("TEST FAILED: " + e.toString()); |
149 throw new RuntimeException("TEST FAILED: " + e.toString()); |
150 } finally { |
150 } finally { |
151 /* |
151 /* |
152 * When all is said and done, try to unexport the remote object |
152 * When all is said and done, try to unexport the remote object |
153 * so that the VM has a chance to exit. |
153 * so that the VM has a chance to exit. |
154 */ |
154 */ |
155 try { |
155 try { |
156 UnicastRemoteObject.unexportObject(impl, true); |
156 UnicastRemoteObject.unexportObject(impl, true); |
157 } catch (Exception e) { |
157 } catch (Exception e) { |
158 } |
158 } |
159 } |
159 } |
160 } |
160 } |
161 } |
161 } |
162 |
162 |
163 class TestSF extends RMISocketFactory { |
163 class TestSF extends RMISocketFactory { |
164 |
164 |