2362N/A * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 2362N/A * published by the Free Software Foundation. Oracle designates this 0N/A * particular file as subject to the "Classpath" exception as provided 2362N/A * by Oracle in the LICENSE file that accompanied this code. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2362N/A * or visit www.oracle.com if you need additional information or have any 0N/A * DGCClient implements the client-side of the RMI distributed garbage 0N/A * collection system. 0N/A * The external interface to DGCClient is the "registerRefs" method. 0N/A * When a LiveRef to a remote object enters the VM, it needs to be 0N/A * registered with the DGCClient to participate in distributed garbage 0N/A * When the first LiveRef to a particular remote object is registered, 0N/A * a "dirty" call is made to the server-side distributed garbage 0N/A * collector for the remote object, which returns a lease guaranteeing 0N/A * that the server-side DGC will not collect the remote object for a 0N/A * certain period of time. While LiveRef instances to remote objects 0N/A * on a particular server exist, the DGCClient periodically sends more 0N/A * "dirty" calls to renew its lease. 0N/A * The DGCClient tracks the local reachability of registered LiveRef 0N/A * instances (using phantom references). When the LiveRef instance 0N/A * for a particular remote object becomes garbage collected locally, 0N/A * a "clean" call is made to the server-side distributed garbage 0N/A * collector, indicating that the server no longer needs to keep the 0N/A * remote object alive for this client. 0N/A * @see java.rmi.dgc.DGC, sun.rmi.transport.DGCImpl 0N/A * @author Ann Wollrath 0N/A * @author Peter Jones 0N/A /** next sequence number for DGC calls (access synchronized on class) */ 0N/A /** unique identifier for this VM as a client of DGC */ 0N/A /** lease duration to request (usually ignored by server) */ 0N/A /** maximum interval between retries of failed clean calls */ 0N/A /** maximum interval between complete garbage collections of local heap */ 0N/A /** minimum retry count for dirty calls that fail */ 0N/A /** retry count for clean calls that fail with ConnectException */ 0N/A /** constant empty ObjID array for lease renewal optimization */ 0N/A /** ObjID for server-side DGC object */ 0N/A * Disallow anyone from creating one of these. 0N/A * Register the LiveRef instances in the supplied list to participate 0N/A * in distributed garbage collection. 0N/A * All of the LiveRefs in the list must be for remote objects at the 0N/A * Look up the given endpoint and register the refs with it. 0N/A * The retrieved entry may get removed from the global endpoint 0N/A * table before EndpointEntry.registerRefs() is able to acquire 0N/A * its lock; in this event, it returns false, and we loop and 0N/A * Get the next sequence number to be used for a dirty or clean 0N/A * operation from this VM. This method should only be called while 0N/A * synchronized on the EndpointEntry whose data structures the 0N/A * operation affects. 0N/A * Given the length of a lease and the time that it was granted, 0N/A * compute the absolute time at which it should be renewed, giving 0N/A * room for reasonable computational and communication delays. 0N/A * REMIND: This algorithm should be more sophisticated, waiting 0N/A * a longer fraction of the lease duration for longer leases. 0N/A * EndpointEntry encapsulates the client-side DGC information specific 0N/A * to a particular Endpoint. Of most significance is the table that 0N/A * maps LiveRef value to RefEntry objects and the renew/clean thread 0N/A * that handles asynchronous client-side DGC operations. 0N/A /** the endpoint that this entry is for */ 0N/A /** synthesized reference to the remote server-side DGC */ 0N/A /** table of refs held for endpoint: maps LiveRef to RefEntry */ 0N/A /** set of RefEntry instances from last (failed) dirty call */ 0N/A /** true if this entry has been removed from the global table */ 0N/A /** absolute time to renew current lease to this endpoint */ 0N/A /** absolute time current lease to this endpoint will expire */ 0N/A /** count of recent dirty calls that have failed */ 0N/A /** absolute time of first recent failed dirty call */ 0N/A /** (average) elapsed time for recent failed dirty calls */ 0N/A /** renew/clean thread for handling lease renewals and clean calls */ 0N/A /** reference queue for phantom references */ 0N/A /** set of clean calls that need to be made */ 0N/A /** global endpoint table: maps Endpoint to EndpointEntry */ 0N/A /** handle for GC latency request (for future cancellation) */ 0N/A * Look up the EndpointEntry for the given Endpoint. An entry is 0N/A * created if one does not already exist. 0N/A * While we are tracking live remote references registered 0N/A * in this VM, request a maximum latency for inspecting the 0N/A * entire heap from the local garbage collector, to place 0N/A * an upper bound on the time to discover remote references 0N/A * that have become unreachable (see bugid 4171278). 0N/A throw new Error(
"internal error creating DGC stub");
0N/A * Register the LiveRef instances in the supplied list to participate 0N/A * in distributed garbage collection. 0N/A * This method returns false if this entry was removed from the 0N/A * global endpoint table (because it was empty) before these refs 0N/A * could be registered. In that case, a new EndpointEntry needs 0N/A * This method must NOT be called while synchronized on this entry. 0N/A synchronized (
this) {
0N/A * Remove the given RefEntry from the ref table. If that makes 0N/A * the ref table empty, remove this entry from the global endpoint 0N/A * This method must ONLY be called while synchronized on this entry. 0N/A * If there are no longer any live remote references 0N/A * registered, we are no longer concerned with the 0N/A * latency of local garbage collection here. 0N/A * Make a DGC dirty call to this entry's endpoint, for the ObjIDs 0N/A * corresponding to the given set of refs and with the given 0N/A * This method must NOT be called while synchronized on this entry. 0N/A synchronized (
this) {
0N/A synchronized (
this) {
0N/A * If this was the first recent failed dirty call, 0N/A * reschedule another one immediately, in case there 0N/A * was just a transient network problem, and remember 0N/A * the start time and duration of this attempt for 0N/A * future calculations of the delays between retries. 0N/A * For each successive failed dirty call, wait for a 0N/A * (binary) exponentially increasing delay before 0N/A * retrying, to avoid network congestion. 0N/A * Calculate the initial retry delay from the 0N/A * average time elapsed for each of the first 0N/A * two failed dirty calls. The result must be 0N/A * at least 1000ms, to prevent a tight loop. 0N/A * Continue if the last known held lease has not 0N/A * expired, or else at least a fixed number of times, 0N/A * or at least until we've tried for a fixed amount 0N/A * of time (the default lease value we request). 0N/A * Give up: postpone lease renewals until next 0N/A * ref is registered for this endpoint. 0N/A * Add all of these refs to the set of refs for this 0N/A * endpoint that may be invalid (this VM may not be in 0N/A * the server's referenced set), so that we will 0N/A * attempt to explicitly dirty them again in the 0N/A * Record that a dirty call has failed for all of these 0N/A * refs, so that clean calls for them in the future 0N/A * If the last known held lease will have expired before 0N/A * the next renewal, all refs might be invalid. 0N/A * Set the absolute time at which the lease for this entry should 0N/A * This method must ONLY be called while synchronized on this entry. 0N/A * RenewCleanThread handles the asynchronous client-side DGC activity 0N/A * for this entry: renewing the leases and making clean calls. 0N/A * Calculate time to block (waiting for phantom 0N/A * reference notifications). It is the time until the 0N/A * lease renewal should be done, bounded on the low 0N/A * end by 1 ms so that the reference queue will always 0N/A * get processed, and if there are pending clean 0N/A * requests (remaining because some clean calls 0N/A * failed), bounded on the high end by the maximum 0N/A * clean call retry interval. 0N/A * Set flag indicating that it is OK to interrupt this 0N/A * thread now, such as if a earlier lease renewal time 0N/A * is set, because we are only going to be blocking 0N/A * and can deal with interrupts. 0N/A * Wait for the duration calculated above for any of 0N/A * our phantom references to be enqueued. 0N/A * Set flag indicating that it is NOT OK to interrupt 0N/A * this thread now, because we may be undertaking I/O 0N/A * operations that should not be interrupted (and we 0N/A * will not be blocking arbitrarily). 0N/A * If there was a phantom reference enqueued, process 0N/A * it and all the rest on the queue, generating 0N/A * clean requests as necessary. 0N/A * Check if it is time to renew this entry's lease. 0N/A * Process the notification of the given phantom reference and any 0N/A * others that are on this entry's reference queue. Each phantom 0N/A * reference is removed from its RefEntry's ref set. All ref 0N/A * entries that have no more registered instances are collected 0N/A * into up to two batched clean call requests: one for refs 0N/A * requiring a "strong" clean call, and one for the rest. 0N/A * This method must ONLY be called while synchronized on this entry. 0N/A * CleanRequest holds the data for the parameters of a clean call 0N/A * that needs to be made. 0N/A /** how many times this request has failed */ 0N/A * Make all of the clean calls described by the clean requests in 0N/A * this entry's set of "pending cleans". Clean requests for clean 0N/A * calls that succeed are removed from the "pending cleans" set. 0N/A * This method must NOT be called while synchronized on this entry. 0N/A * Many types of exceptions here could have been 0N/A * caused by a transient failure, so try again a 0N/A * few times, but not forever. 0N/A * Create an array of ObjIDs (needed for the DGC remote calls) 0N/A * from the ids in the given set of refs. 0N/A * RefEntry encapsulates the client-side DGC information specific 0N/A * to a particular LiveRef value. In particular, it contains a 0N/A * set of phantom references to all of the instances of the LiveRef 0N/A * value registered in the system (but not garbage collected 0N/A /** LiveRef value for this entry (not a registered instance) */ 0N/A /** set of phantom references to registered instances */ 0N/A /** true if a dirty call containing this ref has failed */ 0N/A * Return the LiveRef value for this entry (not a registered 0N/A * Add a LiveRef to the set of registered instances for this entry. 0N/A * This method must ONLY be invoked while synchronized on this 0N/A * RefEntry's EndpointEntry. 0N/A * Only keep a phantom reference to the registered instance, 0N/A * so that it can be garbage collected normally (and we can be 0N/A * notified when that happens). 0N/A * Remove a PhantomLiveRef from the set of registered instances. 0N/A * This method must ONLY be invoked while synchronized on this 0N/A * RefEntry's EndpointEntry. 0N/A * Return true if there are no registered LiveRef instances for 0N/A * this entry still reachable in this VM. 0N/A * This method must ONLY be invoked while synchronized on this 0N/A * RefEntry's EndpointEntry. 0N/A * Record that a dirty call that explicitly contained this 0N/A * entry's ref has failed. 0N/A * This method must ONLY be invoked while synchronized on this 0N/A * RefEntry's EndpointEntry. 0N/A * Return true if a dirty call that explicitly contained this 0N/A * entry's ref has failed (and therefore a clean call for this 0N/A * ref needs to be marked "strong"). 0N/A * This method must ONLY be invoked while synchronized on this 0N/A * RefEntry's EndpointEntry. 0N/A * PhantomLiveRef is a PhantomReference to a LiveRef instance, 0N/A * used to detect when the LiveRef becomes permanently 0N/A * unreachable in this VM.