jdk/src/share/classes/sun/rmi/transport/DGCClient.java
author xdono
Wed, 02 Jul 2008 12:55:45 -0700
changeset 715 f16baef3a20e
parent 51 6fe31bc95bbc
child 5506 202f599c92aa
permissions -rw-r--r--
6719955: Update copyright year Summary: Update copyright year for files that have been modified in 2008 Reviewed-by: ohair, tbell
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
715
f16baef3a20e 6719955: Update copyright year
xdono
parents: 51
diff changeset
     2
 * Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Sun designates this
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
 * by Sun in the LICENSE file that accompanied this code.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    21
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    22
 * CA 95054 USA or visit www.sun.com if you need additional information or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
 * have any questions.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
package sun.rmi.transport;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
import java.lang.ref.PhantomReference;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.lang.ref.ReferenceQueue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.security.AccessController;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.security.PrivilegedAction;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.util.HashMap;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
import java.util.HashSet;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
import java.util.Iterator;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
import java.util.List;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
import java.util.Map;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
import java.util.Set;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
import java.rmi.ConnectException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
import java.rmi.RemoteException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
import java.rmi.dgc.DGC;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
import java.rmi.dgc.Lease;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
import java.rmi.dgc.VMID;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
import java.rmi.server.ObjID;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
import sun.misc.GC;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
import sun.rmi.runtime.NewThreadAction;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
import sun.rmi.server.UnicastRef;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
import sun.rmi.server.Util;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
import sun.security.action.GetLongAction;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 * DGCClient implements the client-side of the RMI distributed garbage
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 * collection system.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 * The external interface to DGCClient is the "registerRefs" method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
 * When a LiveRef to a remote object enters the VM, it needs to be
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 * registered with the DGCClient to participate in distributed garbage
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 * collection.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 * When the first LiveRef to a particular remote object is registered,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
 * a "dirty" call is made to the server-side distributed garbage
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
 * collector for the remote object, which returns a lease guaranteeing
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
 * that the server-side DGC will not collect the remote object for a
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
 * certain period of time.  While LiveRef instances to remote objects
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
 * on a particular server exist, the DGCClient periodically sends more
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
 * "dirty" calls to renew its lease.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
 * The DGCClient tracks the local reachability of registered LiveRef
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
 * instances (using phantom references).  When the LiveRef instance
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
 * for a particular remote object becomes garbage collected locally,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
 * a "clean" call is made to the server-side distributed garbage
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
 * collector, indicating that the server no longer needs to keep the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
 * remote object alive for this client.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
 * @see java.rmi.dgc.DGC, sun.rmi.transport.DGCImpl
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
 * @author  Ann Wollrath
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
 * @author  Peter Jones
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
final class DGCClient {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
    /** next sequence number for DGC calls (access synchronized on class) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
    private static long nextSequenceNum = Long.MIN_VALUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
    /** unique identifier for this VM as a client of DGC */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
    private static VMID vmid = new VMID();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
    /** lease duration to request (usually ignored by server) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
    private static final long leaseValue =              // default 10 minutes
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
    88
        AccessController.doPrivileged(
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
            new GetLongAction("java.rmi.dgc.leaseValue",
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
    90
                              600000)).longValue();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
    /** maximum interval between retries of failed clean calls */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
    private static final long cleanInterval =           // default 3 minutes
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
    94
        AccessController.doPrivileged(
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
            new GetLongAction("sun.rmi.dgc.cleanInterval",
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
    96
                              180000)).longValue();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
    /** maximum interval between complete garbage collections of local heap */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
    private static final long gcInterval =              // default 1 hour
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   100
        AccessController.doPrivileged(
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
            new GetLongAction("sun.rmi.dgc.client.gcInterval",
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   102
                              3600000)).longValue();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
    /** minimum retry count for dirty calls that fail */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
    private static final int dirtyFailureRetries = 5;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
    /** retry count for clean calls that fail with ConnectException */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
    private static final int cleanFailureRetries = 5;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
    /** constant empty ObjID array for lease renewal optimization */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
    private static final ObjID[] emptyObjIDArray = new ObjID[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
    /** ObjID for server-side DGC object */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
    private static final ObjID dgcID = new ObjID(ObjID.DGC_ID);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
     * Disallow anyone from creating one of these.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
    private DGCClient() {}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
     * Register the LiveRef instances in the supplied list to participate
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
     * in distributed garbage collection.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
     * All of the LiveRefs in the list must be for remote objects at the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
     * given endpoint.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
    static void registerRefs(Endpoint ep, List refs) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
         * Look up the given endpoint and register the refs with it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
         * The retrieved entry may get removed from the global endpoint
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
         * table before EndpointEntry.registerRefs() is able to acquire
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
         * its lock; in this event, it returns false, and we loop and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
         * try again.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
        EndpointEntry epEntry;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
        do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
            epEntry = EndpointEntry.lookup(ep);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
        } while (!epEntry.registerRefs(refs));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
     * Get the next sequence number to be used for a dirty or clean
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
     * operation from this VM.  This method should only be called while
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
     * synchronized on the EndpointEntry whose data structures the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
     * operation affects.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
    private static synchronized long getNextSequenceNum() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
        return nextSequenceNum++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
     * Given the length of a lease and the time that it was granted,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
     * compute the absolute time at which it should be renewed, giving
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
     * room for reasonable computational and communication delays.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
    private static long computeRenewTime(long grantTime, long duration) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
         * REMIND: This algorithm should be more sophisticated, waiting
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
         * a longer fraction of the lease duration for longer leases.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
        return grantTime + (duration / 2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
     * EndpointEntry encapsulates the client-side DGC information specific
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
     * to a particular Endpoint.  Of most significance is the table that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
     * maps LiveRef value to RefEntry objects and the renew/clean thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
     * that handles asynchronous client-side DGC operations.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
    private static class EndpointEntry {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
        /** the endpoint that this entry is for */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
        private Endpoint endpoint;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
        /** synthesized reference to the remote server-side DGC */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
        private DGC dgc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
        /** table of refs held for endpoint: maps LiveRef to RefEntry */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
        private Map refTable = new HashMap(5);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
        /** set of RefEntry instances from last (failed) dirty call */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
        private Set invalidRefs = new HashSet(5);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
        /** true if this entry has been removed from the global table */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
        private boolean removed = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
        /** absolute time to renew current lease to this endpoint */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
        private long renewTime = Long.MAX_VALUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
        /** absolute time current lease to this endpoint will expire */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
        private long expirationTime = Long.MIN_VALUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
        /** count of recent dirty calls that have failed */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
        private int dirtyFailures = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
        /** absolute time of first recent failed dirty call */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
        private long dirtyFailureStartTime;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
        /** (average) elapsed time for recent failed dirty calls */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
        private long dirtyFailureDuration;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
        /** renew/clean thread for handling lease renewals and clean calls */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
        private Thread renewCleanThread;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
        /** true if renew/clean thread may be interrupted */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
        private boolean interruptible = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
        /** reference queue for phantom references */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
        private ReferenceQueue refQueue = new ReferenceQueue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
        /** set of clean calls that need to be made */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
        private Set pendingCleans = new HashSet(5);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
        /** global endpoint table: maps Endpoint to EndpointEntry */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
        private static Map endpointTable = new HashMap(5);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
        /** handle for GC latency request (for future cancellation) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
        private static GC.LatencyRequest gcLatencyRequest = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
         * Look up the EndpointEntry for the given Endpoint.  An entry is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
         * created if one does not already exist.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
        public static EndpointEntry lookup(Endpoint ep) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
            synchronized (endpointTable) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
                EndpointEntry entry = (EndpointEntry) endpointTable.get(ep);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
                if (entry == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
                    entry = new EndpointEntry(ep);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
                    endpointTable.put(ep, entry);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
                    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
                     * While we are tracking live remote references registered
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
                     * in this VM, request a maximum latency for inspecting the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
                     * entire heap from the local garbage collector, to place
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
                     * an upper bound on the time to discover remote references
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
                     * that have become unreachable (see bugid 4171278).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
                     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
                    if (gcLatencyRequest == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
                        gcLatencyRequest = GC.requestLatency(gcInterval);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
                return entry;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
        private EndpointEntry(final Endpoint endpoint) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
            this.endpoint = endpoint;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
                LiveRef dgcRef = new LiveRef(dgcID, endpoint, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
                dgc = (DGC) Util.createProxy(DGCImpl.class,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
                                             new UnicastRef(dgcRef), true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
            } catch (RemoteException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
                throw new Error("internal error creating DGC stub");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
            }
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   246
            renewCleanThread =  AccessController.doPrivileged(
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
                new NewThreadAction(new RenewCleanThread(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
                                    "RenewClean-" + endpoint, true));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
            renewCleanThread.start();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
         * Register the LiveRef instances in the supplied list to participate
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
         * in distributed garbage collection.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
         * This method returns false if this entry was removed from the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
         * global endpoint table (because it was empty) before these refs
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
         * could be registered.  In that case, a new EndpointEntry needs
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
         * to be looked up.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
         * This method must NOT be called while synchronized on this entry.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
        public boolean registerRefs(List refs) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
            assert !Thread.holdsLock(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
            Set refsToDirty = null;     // entries for refs needing dirty
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
            long sequenceNum;           // sequence number for dirty call
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
            synchronized (this) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
                if (removed) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
                    return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
                Iterator iter = refs.iterator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
                while (iter.hasNext()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
                    LiveRef ref = (LiveRef) iter.next();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
                    assert ref.getEndpoint().equals(endpoint);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
                    RefEntry refEntry = (RefEntry) refTable.get(ref);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
                    if (refEntry == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
                        LiveRef refClone = (LiveRef) ref.clone();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
                        refEntry = new RefEntry(refClone);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
                        refTable.put(refClone, refEntry);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
                        if (refsToDirty == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
                            refsToDirty = new HashSet(5);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
                        refsToDirty.add(refEntry);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
                    refEntry.addInstanceToRefSet(ref);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
                if (refsToDirty == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
                    return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
                refsToDirty.addAll(invalidRefs);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
                invalidRefs.clear();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
                sequenceNum = getNextSequenceNum();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
            makeDirtyCall(refsToDirty, sequenceNum);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
            return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
         * Remove the given RefEntry from the ref table.  If that makes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
         * the ref table empty, remove this entry from the global endpoint
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
         * table.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
         * This method must ONLY be called while synchronized on this entry.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
        private void removeRefEntry(RefEntry refEntry) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
            assert Thread.holdsLock(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
            assert !removed;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
            assert refTable.containsKey(refEntry.getRef());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
            refTable.remove(refEntry.getRef());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
            invalidRefs.remove(refEntry);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
            if (refTable.isEmpty()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
                synchronized (endpointTable) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
                    endpointTable.remove(endpoint);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
                    Transport transport = endpoint.getOutboundTransport();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
                    transport.free(endpoint);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
                    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
                     * If there are no longer any live remote references
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
                     * registered, we are no longer concerned with the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
                     * latency of local garbage collection here.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
                     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
                    if (endpointTable.isEmpty()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
                        assert gcLatencyRequest != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
                        gcLatencyRequest.cancel();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
                        gcLatencyRequest = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
                    removed = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
         * Make a DGC dirty call to this entry's endpoint, for the ObjIDs
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
         * corresponding to the given set of refs and with the given
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
         * sequence number.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
         * This method must NOT be called while synchronized on this entry.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
        private void makeDirtyCall(Set refEntries, long sequenceNum) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
            assert !Thread.holdsLock(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
            ObjID[] ids;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
            if (refEntries != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
                ids = createObjIDArray(refEntries);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
                ids = emptyObjIDArray;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
            long startTime = System.currentTimeMillis();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
                Lease lease =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
                    dgc.dirty(ids, sequenceNum, new Lease(vmid, leaseValue));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
                long duration = lease.getValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
                long newRenewTime = computeRenewTime(startTime, duration);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
                long newExpirationTime = startTime + duration;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
                synchronized (this) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
                    dirtyFailures = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
                    setRenewTime(newRenewTime);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
                    expirationTime = newExpirationTime;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
            } catch (Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
                long endTime = System.currentTimeMillis();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
                synchronized (this) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
                    dirtyFailures++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
                    if (dirtyFailures == 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
                        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
                         * If this was the first recent failed dirty call,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
                         * reschedule another one immediately, in case there
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
                         * was just a transient network problem, and remember
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
                         * the start time and duration of this attempt for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
                         * future calculations of the delays between retries.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
                         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
                        dirtyFailureStartTime = startTime;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
                        dirtyFailureDuration = endTime - startTime;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
                        setRenewTime(endTime);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
                        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
                         * For each successive failed dirty call, wait for a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
                         * (binary) exponentially increasing delay before
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
                         * retrying, to avoid network congestion.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
                         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
                        int n = dirtyFailures - 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
                        if (n == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
                            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
                             * Calculate the initial retry delay from the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
                             * average time elapsed for each of the first
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
                             * two failed dirty calls.  The result must be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
                             * at least 1000ms, to prevent a tight loop.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
                             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
                            dirtyFailureDuration =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
                                Math.max((dirtyFailureDuration +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
                                          (endTime - startTime)) >> 1, 1000);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
                        long newRenewTime =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
                            endTime + (dirtyFailureDuration << n);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
                        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
                         * Continue if the last known held lease has not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
                         * expired, or else at least a fixed number of times,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
                         * or at least until we've tried for a fixed amount
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
                         * of time (the default lease value we request).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
                         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
                        if (newRenewTime < expirationTime ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
                            dirtyFailures < dirtyFailureRetries ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
                            newRenewTime < dirtyFailureStartTime + leaseValue)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
                        {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
                            setRenewTime(newRenewTime);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
                        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
                            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
                             * Give up: postpone lease renewals until next
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
                             * ref is registered for this endpoint.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
                             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
                            setRenewTime(Long.MAX_VALUE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
                    if (refEntries != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
                        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
                         * Add all of these refs to the set of refs for this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
                         * endpoint that may be invalid (this VM may not be in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
                         * the server's referenced set), so that we will
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
                         * attempt to explicitly dirty them again in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
                         * future.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
                         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
                        invalidRefs.addAll(refEntries);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
                        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
                         * Record that a dirty call has failed for all of these
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
                         * refs, so that clean calls for them in the future
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
                         * will be strong.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
                         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
                        Iterator iter = refEntries.iterator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
                        while (iter.hasNext()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
                            RefEntry refEntry = (RefEntry) iter.next();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
                            refEntry.markDirtyFailed();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
                    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
                     * If the last known held lease will have expired before
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
                     * the next renewal, all refs might be invalid.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
                     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
                    if (renewTime >= expirationTime) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
                        invalidRefs.addAll(refTable.values());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
         * Set the absolute time at which the lease for this entry should
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
         * be renewed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
         * This method must ONLY be called while synchronized on this entry.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
        private void setRenewTime(long newRenewTime) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
            assert Thread.holdsLock(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
            if (newRenewTime < renewTime) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
                renewTime = newRenewTime;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
                if (interruptible) {
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   476
                    AccessController.doPrivileged(
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   477
                        new PrivilegedAction<Void>() {
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   478
                            public Void run() {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
                            renewCleanThread.interrupt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
                            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
                    });
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
                renewTime = newRenewTime;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
         * RenewCleanThread handles the asynchronous client-side DGC activity
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
         * for this entry: renewing the leases and making clean calls.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
        private class RenewCleanThread implements Runnable {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
            public void run() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
                do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
                    long timeToWait;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
                    RefEntry.PhantomLiveRef phantom = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
                    boolean needRenewal = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
                    Set refsToDirty = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
                    long sequenceNum = Long.MIN_VALUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
                    synchronized (EndpointEntry.this) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
                        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
                         * Calculate time to block (waiting for phantom
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
                         * reference notifications).  It is the time until the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
                         * lease renewal should be done, bounded on the low
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
                         * end by 1 ms so that the reference queue will always
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
                         * get processed, and if there are pending clean
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
                         * requests (remaining because some clean calls
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
                         * failed), bounded on the high end by the maximum
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
                         * clean call retry interval.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
                         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
                        long timeUntilRenew =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
                            renewTime - System.currentTimeMillis();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
                        timeToWait = Math.max(timeUntilRenew, 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
                        if (!pendingCleans.isEmpty()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
                            timeToWait = Math.min(timeToWait, cleanInterval);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
                        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
                         * Set flag indicating that it is OK to interrupt this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
                         * thread now, such as if a earlier lease renewal time
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
                         * is set, because we are only going to be blocking
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
                         * and can deal with interrupts.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
                         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
                        interruptible = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
                    try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
                        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
                         * Wait for the duration calculated above for any of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
                         * our phantom references to be enqueued.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
                         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
                        phantom = (RefEntry.PhantomLiveRef)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
                            refQueue.remove(timeToWait);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
                    } catch (InterruptedException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
                    synchronized (EndpointEntry.this) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
                        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
                         * Set flag indicating that it is NOT OK to interrupt
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
                         * this thread now, because we may be undertaking I/O
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
                         * operations that should not be interrupted (and we
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
                         * will not be blocking arbitrarily).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
                         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
                        interruptible = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
                        Thread.interrupted();   // clear interrupted state
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
                        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
                         * If there was a phantom reference enqueued, process
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
                         * it and all the rest on the queue, generating
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
                         * clean requests as necessary.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
                         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
                        if (phantom != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
                            processPhantomRefs(phantom);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
                        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
                         * Check if it is time to renew this entry's lease.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
                         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
                        long currentTime = System.currentTimeMillis();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
                        if (currentTime > renewTime) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
                            needRenewal = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
                            if (!invalidRefs.isEmpty()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
                                refsToDirty = invalidRefs;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
                                invalidRefs = new HashSet(5);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
                            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
                            sequenceNum = getNextSequenceNum();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
                    if (needRenewal) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
                        makeDirtyCall(refsToDirty, sequenceNum);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
                    if (!pendingCleans.isEmpty()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
                        makeCleanCalls();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
                } while (!removed || !pendingCleans.isEmpty());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
         * Process the notification of the given phantom reference and any
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
         * others that are on this entry's reference queue.  Each phantom
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
         * reference is removed from its RefEntry's ref set.  All ref
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
         * entries that have no more registered instances are collected
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
         * into up to two batched clean call requests: one for refs
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
         * requiring a "strong" clean call, and one for the rest.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
         * This method must ONLY be called while synchronized on this entry.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
        private void processPhantomRefs(RefEntry.PhantomLiveRef phantom) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
            assert Thread.holdsLock(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
            Set strongCleans = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
            Set normalCleans = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
            do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
                RefEntry refEntry = phantom.getRefEntry();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
                refEntry.removeInstanceFromRefSet(phantom);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
                if (refEntry.isRefSetEmpty()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
                    if (refEntry.hasDirtyFailed()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
                        if (strongCleans == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
                            strongCleans = new HashSet(5);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
                        strongCleans.add(refEntry);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
                        if (normalCleans == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
                            normalCleans = new HashSet(5);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
                        normalCleans.add(refEntry);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
                    removeRefEntry(refEntry);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
            } while ((phantom =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
                (RefEntry.PhantomLiveRef) refQueue.poll()) != null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
            if (strongCleans != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
                pendingCleans.add(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
                    new CleanRequest(createObjIDArray(strongCleans),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
                                     getNextSequenceNum(), true));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
            if (normalCleans != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
                pendingCleans.add(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
                    new CleanRequest(createObjIDArray(normalCleans),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
                                     getNextSequenceNum(), false));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
         * CleanRequest holds the data for the parameters of a clean call
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
         * that needs to be made.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
        private static class CleanRequest {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
            final ObjID[] objIDs;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
            final long sequenceNum;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
            final boolean strong;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
            /** how many times this request has failed */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
            int failures = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
            CleanRequest(ObjID[] objIDs, long sequenceNum, boolean strong) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
                this.objIDs = objIDs;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
                this.sequenceNum = sequenceNum;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
                this.strong = strong;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
         * Make all of the clean calls described by the clean requests in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
         * this entry's set of "pending cleans".  Clean requests for clean
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
         * calls that succeed are removed from the "pending cleans" set.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
         * This method must NOT be called while synchronized on this entry.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
        private void makeCleanCalls() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
            assert !Thread.holdsLock(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
            Iterator iter = pendingCleans.iterator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
            while (iter.hasNext()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
                CleanRequest request = (CleanRequest) iter.next();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
                try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
                    dgc.clean(request.objIDs, request.sequenceNum, vmid,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
                              request.strong);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
                    iter.remove();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
                } catch (Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
                    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
                     * Many types of exceptions here could have been
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
                     * caused by a transient failure, so try again a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
                     * few times, but not forever.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
                     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
                    if (++request.failures >= cleanFailureRetries) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
                        iter.remove();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
         * Create an array of ObjIDs (needed for the DGC remote calls)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
         * from the ids in the given set of refs.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
        private static ObjID[] createObjIDArray(Set refEntries) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
            ObjID[] ids = new ObjID[refEntries.size()];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
            Iterator iter = refEntries.iterator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
            for (int i = 0; i < ids.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
                ids[i] = ((RefEntry) iter.next()).getRef().getObjID();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
            return ids;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
         * RefEntry encapsulates the client-side DGC information specific
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
         * to a particular LiveRef value.  In particular, it contains a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
         * set of phantom references to all of the instances of the LiveRef
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
         * value registered in the system (but not garbage collected
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
         * locally).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
        private class RefEntry {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
            /** LiveRef value for this entry (not a registered instance) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
            private LiveRef ref;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
            /** set of phantom references to registered instances */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
            private Set refSet = new HashSet(5);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
            /** true if a dirty call containing this ref has failed */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
            private boolean dirtyFailed = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
            public RefEntry(LiveRef ref) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
                this.ref = ref;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
            /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
             * Return the LiveRef value for this entry (not a registered
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
             * instance).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
            public LiveRef getRef() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
                return ref;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
            /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
             * Add a LiveRef to the set of registered instances for this entry.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
             * This method must ONLY be invoked while synchronized on this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
             * RefEntry's EndpointEntry.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
            public void addInstanceToRefSet(LiveRef ref) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
                assert Thread.holdsLock(EndpointEntry.this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
                assert ref.equals(this.ref);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
                 * Only keep a phantom reference to the registered instance,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
                 * so that it can be garbage collected normally (and we can be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
                 * notified when that happens).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
                refSet.add(new PhantomLiveRef(ref));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
            /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
             * Remove a PhantomLiveRef from the set of registered instances.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   744
             * This method must ONLY be invoked while synchronized on this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
             * RefEntry's EndpointEntry.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
            public void removeInstanceFromRefSet(PhantomLiveRef phantom) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
                assert Thread.holdsLock(EndpointEntry.this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
                assert refSet.contains(phantom);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
                refSet.remove(phantom);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
            /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
             * Return true if there are no registered LiveRef instances for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
             * this entry still reachable in this VM.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
             * This method must ONLY be invoked while synchronized on this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
             * RefEntry's EndpointEntry.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
            public boolean isRefSetEmpty() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
                assert Thread.holdsLock(EndpointEntry.this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
                return refSet.size() == 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
            /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
             * Record that a dirty call that explicitly contained this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
             * entry's ref has failed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
             * This method must ONLY be invoked while synchronized on this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
             * RefEntry's EndpointEntry.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   772
            public void markDirtyFailed() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
                assert Thread.holdsLock(EndpointEntry.this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
                dirtyFailed = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
            /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
             * Return true if a dirty call that explicitly contained this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
             * entry's ref has failed (and therefore a clean call for this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
             * ref needs to be marked "strong").
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
             * This method must ONLY be invoked while synchronized on this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
             * RefEntry's EndpointEntry.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
            public boolean hasDirtyFailed() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
                assert Thread.holdsLock(EndpointEntry.this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
                return dirtyFailed;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
            /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
             * PhantomLiveRef is a PhantomReference to a LiveRef instance,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
             * used to detect when the LiveRef becomes permanently
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
             * unreachable in this VM.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
            private class PhantomLiveRef extends PhantomReference {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
                public PhantomLiveRef(LiveRef ref) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
                    super(ref, EndpointEntry.this.refQueue);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
                public RefEntry getRefEntry() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
                    return RefEntry.this;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
}