Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/src/share/classes/sun/rmi/transport/DGCImpl.java
+++ new/src/share/classes/sun/rmi/transport/DGCImpl.java
1 1 /*
2 2 * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 4 *
5 5 * This code is free software; you can redistribute it and/or modify it
6 6 * under the terms of the GNU General Public License version 2 only, as
7 7 * published by the Free Software Foundation. Oracle designates this
8 8 * particular file as subject to the "Classpath" exception as provided
9 9 * by Oracle in the LICENSE file that accompanied this code.
10 10 *
11 11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 14 * version 2 for more details (a copy is included in the LICENSE file that
15 15 * accompanied this code).
16 16 *
17 17 * You should have received a copy of the GNU General Public License version
18 18 * 2 along with this work; if not, write to the Free Software Foundation,
19 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 20 *
21 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 22 * or visit www.oracle.com if you need additional information or have any
23 23 * questions.
24 24 */
25 25 package sun.rmi.transport;
26 26
27 27 import java.rmi.Remote;
28 28 import java.rmi.RemoteException;
29 29 import java.rmi.dgc.DGC;
30 30 import java.rmi.dgc.Lease;
31 31 import java.rmi.dgc.VMID;
32 32 import java.rmi.server.LogStream;
33 33 import java.rmi.server.ObjID;
34 34 import java.rmi.server.RemoteServer;
35 35 import java.rmi.server.ServerNotActiveException;
36 36 import java.security.AccessController;
37 37 import java.security.PrivilegedAction;
38 38 import java.util.ArrayList;
39 39 import java.util.HashSet;
40 40 import java.util.HashMap;
41 41 import java.util.Iterator;
42 42 import java.util.List;
43 43 import java.util.Map;
44 44 import java.util.Set;
45 45 import java.util.concurrent.Future;
46 46 import java.util.concurrent.ScheduledExecutorService;
47 47 import java.util.concurrent.TimeUnit;
48 48 import sun.rmi.runtime.Log;
49 49 import sun.rmi.runtime.RuntimeUtil;
50 50 import sun.rmi.server.UnicastRef;
51 51 import sun.rmi.server.UnicastServerRef;
52 52 import sun.rmi.server.Util;
53 53 import sun.security.action.GetLongAction;
54 54 import sun.security.action.GetPropertyAction;
55 55
56 56 /**
57 57 * This class implements the guts of the server-side distributed GC
58 58 * algorithm
59 59 *
60 60 * @author Ann Wollrath
61 61 */
62 62 final class DGCImpl implements DGC {
63 63
64 64 /* dgc system log */
65 65 static final Log dgcLog = Log.getLog("sun.rmi.dgc", "dgc",
66 66 LogStream.parseLevel(AccessController.doPrivileged(
67 67 new GetPropertyAction("sun.rmi.dgc.logLevel"))));
68 68
69 69 /** lease duration to grant to clients */
70 70 private static final long leaseValue = // default 10 minutes
71 71 AccessController.doPrivileged(
72 72 new GetLongAction("java.rmi.dgc.leaseValue", 600000));
73 73
74 74 /** lease check interval; default is half of lease grant duration */
75 75 private static final long leaseCheckInterval =
76 76 AccessController.doPrivileged(
↓ open down ↓ |
76 lines elided |
↑ open up ↑ |
77 77 new GetLongAction("sun.rmi.dgc.checkInterval", leaseValue / 2));
78 78
79 79 /** thread pool for scheduling delayed tasks */
80 80 private static final ScheduledExecutorService scheduler =
81 81 AccessController.doPrivileged(
82 82 new RuntimeUtil.GetInstanceAction()).getScheduler();
83 83
84 84 /** remote implementation of DGC interface for this VM */
85 85 private static DGCImpl dgc;
86 86 /** table that maps VMID to LeaseInfo */
87 - private Map<VMID,LeaseInfo> leaseTable = new HashMap<VMID,LeaseInfo>();
87 + private Map<VMID,LeaseInfo> leaseTable = new HashMap<>();
88 88 /** checks for lease expiration */
89 89 private Future<?> checker = null;
90 90
91 91 /**
92 92 * Return the remote implementation of the DGC interface for
93 93 * this VM.
94 94 */
95 95 static DGCImpl getDGCImpl() {
96 96 return dgc;
97 97 }
98 98
99 99 /**
100 100 * Construct a new server-side remote object collector at
101 101 * a particular port. Disallow construction from outside.
102 102 */
103 103 private DGCImpl() {}
104 104
105 105 /**
106 106 * The dirty call adds the VMID "vmid" to the set of clients
107 107 * that hold references to the object associated with the ObjID
108 108 * id. The long "sequenceNum" is used to detect late dirty calls. If
109 109 * the VMID "vmid" is null, a VMID will be generated on the
110 110 * server (for use by the client in subsequent calls) and
111 111 * returned.
112 112 *
113 113 * The client must call the "dirty" method to renew the lease
114 114 * before the "lease" time expires or all references to remote
115 115 * objects in this VM that the client holds are considered
116 116 * "unreferenced".
117 117 */
118 118 public Lease dirty(ObjID[] ids, long sequenceNum, Lease lease) {
119 119 VMID vmid = lease.getVMID();
120 120 /*
121 121 * The server specifies the lease value; the client has
122 122 * no say in the matter.
123 123 */
124 124 long duration = leaseValue;
125 125
126 126 if (dgcLog.isLoggable(Log.VERBOSE)) {
127 127 dgcLog.log(Log.VERBOSE, "vmid = " + vmid);
128 128 }
129 129
130 130 // create a VMID if one wasn't supplied
131 131 if (vmid == null) {
132 132 vmid = new VMID();
133 133
134 134 if (dgcLog.isLoggable(Log.BRIEF)) {
135 135 String clientHost;
136 136 try {
137 137 clientHost = RemoteServer.getClientHost();
138 138 } catch (ServerNotActiveException e) {
139 139 clientHost = "<unknown host>";
140 140 }
141 141 dgcLog.log(Log.BRIEF, " assigning vmid " + vmid +
142 142 " to client " + clientHost);
143 143 }
144 144 }
145 145
146 146 lease = new Lease(vmid, duration);
147 147 // record lease information
148 148 synchronized (leaseTable) {
149 149 LeaseInfo info = leaseTable.get(vmid);
150 150 if (info == null) {
151 151 leaseTable.put(vmid, new LeaseInfo(vmid, duration));
152 152 if (checker == null) {
153 153 checker = scheduler.scheduleWithFixedDelay(
154 154 new Runnable() {
155 155 public void run() {
156 156 checkLeases();
157 157 }
158 158 },
159 159 leaseCheckInterval,
160 160 leaseCheckInterval, TimeUnit.MILLISECONDS);
161 161 }
162 162 } else {
163 163 info.renew(duration);
164 164 }
165 165 }
166 166
167 167 for (ObjID id : ids) {
168 168 if (dgcLog.isLoggable(Log.VERBOSE)) {
169 169 dgcLog.log(Log.VERBOSE, "id = " + id +
170 170 ", vmid = " + vmid + ", duration = " + duration);
171 171 }
172 172
173 173 ObjectTable.referenced(id, sequenceNum, vmid);
174 174 }
175 175
176 176 // return the VMID used
177 177 return lease;
178 178 }
179 179
180 180 /**
181 181 * The clean call removes the VMID from the set of clients
182 182 * that hold references to the object associated with the LiveRef
183 183 * ref. The sequence number is used to detect late clean calls. If the
184 184 * argument "strong" is true, then the clean call is a result of a
185 185 * failed "dirty" call, thus the sequence number for the VMID needs
186 186 * to be remembered until the client goes away.
187 187 */
188 188 public void clean(ObjID[] ids, long sequenceNum, VMID vmid, boolean strong)
189 189 {
190 190 for (ObjID id : ids) {
191 191 if (dgcLog.isLoggable(Log.VERBOSE)) {
192 192 dgcLog.log(Log.VERBOSE, "id = " + id +
193 193 ", vmid = " + vmid + ", strong = " + strong);
194 194 }
195 195
196 196 ObjectTable.unreferenced(id, sequenceNum, vmid, strong);
197 197 }
198 198 }
199 199
200 200 /**
201 201 * Register interest in receiving a callback when this VMID
202 202 * becomes inaccessible.
203 203 */
204 204 void registerTarget(VMID vmid, Target target) {
205 205 synchronized (leaseTable) {
206 206 LeaseInfo info = leaseTable.get(vmid);
207 207 if (info == null) {
208 208 target.vmidDead(vmid);
209 209 } else {
210 210 info.notifySet.add(target);
211 211 }
212 212 }
213 213 }
214 214
215 215 /**
216 216 * Remove notification request.
217 217 */
218 218 void unregisterTarget(VMID vmid, Target target) {
219 219 synchronized (leaseTable) {
220 220 LeaseInfo info = leaseTable.get(vmid);
221 221 if (info != null) {
222 222 info.notifySet.remove(target);
223 223 }
224 224 }
225 225 }
226 226
227 227 /**
228 228 * Check if leases have expired. If a lease has expired, remove
↓ open down ↓ |
131 lines elided |
↑ open up ↑ |
229 229 * it from the table and notify all interested parties that the
230 230 * VMID is essentially "dead".
231 231 *
232 232 * @return if true, there are leases outstanding; otherwise leases
233 233 * no longer need to be checked
234 234 */
235 235 private void checkLeases() {
236 236 long time = System.currentTimeMillis();
237 237
238 238 /* List of vmids that need to be removed from the leaseTable */
239 - List<LeaseInfo> toUnregister = new ArrayList<LeaseInfo>();
239 + List<LeaseInfo> toUnregister = new ArrayList<>();
240 240
241 241 /* Build a list of leaseInfo objects that need to have
242 242 * targets removed from their notifySet. Remove expired
243 243 * leases from leaseTable.
244 244 */
245 245 synchronized (leaseTable) {
246 246 Iterator<LeaseInfo> iter = leaseTable.values().iterator();
247 247 while (iter.hasNext()) {
248 248 LeaseInfo info = iter.next();
249 249 if (info.expired(time)) {
250 250 toUnregister.add(info);
251 251 iter.remove();
252 252 }
253 253 }
254 254
255 255 if (leaseTable.isEmpty()) {
256 256 checker.cancel(false);
257 257 checker = null;
258 258 }
259 259 }
260 260
261 261 /* Notify and unegister targets without holding the lock on
262 262 * the leaseTable so we avoid deadlock.
263 263 */
264 264 for (LeaseInfo info : toUnregister) {
265 265 for (Target target : info.notifySet) {
266 266 target.vmidDead(info.vmid);
267 267 }
268 268 }
269 269 }
270 270
271 271 static {
272 272 /*
273 273 * "Export" the singleton DGCImpl in a context isolated from
274 274 * the arbitrary current thread context.
275 275 */
276 276 AccessController.doPrivileged(new PrivilegedAction<Void>() {
277 277 public Void run() {
278 278 ClassLoader savedCcl =
279 279 Thread.currentThread().getContextClassLoader();
280 280 try {
281 281 Thread.currentThread().setContextClassLoader(
282 282 ClassLoader.getSystemClassLoader());
283 283
284 284 /*
285 285 * Put remote collector object in table by hand to prevent
286 286 * listen on port. (UnicastServerRef.exportObject would
287 287 * cause transport to listen.)
288 288 */
289 289 try {
290 290 dgc = new DGCImpl();
291 291 ObjID dgcID = new ObjID(ObjID.DGC_ID);
292 292 LiveRef ref = new LiveRef(dgcID, 0);
293 293 UnicastServerRef disp = new UnicastServerRef(ref);
294 294 Remote stub =
295 295 Util.createProxy(DGCImpl.class,
296 296 new UnicastRef(ref), true);
297 297 disp.setSkeleton(dgc);
298 298 Target target =
299 299 new Target(dgc, disp, stub, dgcID, true);
300 300 ObjectTable.putTarget(target);
301 301 } catch (RemoteException e) {
302 302 throw new Error(
303 303 "exception initializing server-side DGC", e);
304 304 }
305 305 } finally {
↓ open down ↓ |
56 lines elided |
↑ open up ↑ |
306 306 Thread.currentThread().setContextClassLoader(savedCcl);
307 307 }
308 308 return null;
309 309 }
310 310 });
311 311 }
312 312
313 313 private static class LeaseInfo {
314 314 VMID vmid;
315 315 long expiration;
316 - Set<Target> notifySet = new HashSet<Target>();
316 + Set<Target> notifySet = new HashSet<>();
317 317
318 318 LeaseInfo(VMID vmid, long lease) {
319 319 this.vmid = vmid;
320 320 expiration = System.currentTimeMillis() + lease;
321 321 }
322 322
323 323 synchronized void renew(long lease) {
324 324 long newExpiration = System.currentTimeMillis() + lease;
325 325 if (newExpiration > expiration)
326 326 expiration = newExpiration;
327 327 }
328 328
329 329 boolean expired(long time) {
330 330 if (expiration < time) {
331 331 if (dgcLog.isLoggable(Log.BRIEF)) {
332 332 dgcLog.log(Log.BRIEF, vmid.toString());
333 333 }
334 334 return true;
335 335 } else {
336 336 return false;
337 337 }
338 338 }
339 339 }
340 340 }
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX