You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@river.apache.org by pe...@apache.org on 2014/05/09 09:03:19 UTC
svn commit: r1593493 [8/24] - in /river/jtsk/skunk/qa_refactor/trunk: qa/
qa/src/com/sun/jini/test/impl/end2end/jssewrapper/
qa/src/com/sun/jini/test/impl/joinmanager/
qa/src/com/sun/jini/test/impl/mahalo/
qa/src/com/sun/jini/test/impl/outrigger/matchi...
Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerImpl.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerImpl.java?rev=1593493&r1=1593492&r2=1593493&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerImpl.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerImpl.java Fri May 9 07:03:18 2014
@@ -1,8146 +1,8146 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.sun.jini.fiddler;
-
-import com.sun.jini.config.Config;
-
-import com.sun.jini.constants.ThrowableConstants;
-import com.sun.jini.constants.TimeConstants;
-import com.sun.jini.constants.VersionConstants;
-
-import com.sun.jini.logging.Levels;
-
-import com.sun.jini.lookup.entry.BasicServiceType;
-import com.sun.jini.lookup.entry.LookupAttributes;
-
-import com.sun.jini.proxy.ThrowThis;
-
-import com.sun.jini.reliableLog.ReliableLog;
-import com.sun.jini.reliableLog.LogHandler;
-
-import com.sun.jini.start.LifeCycle;
-import org.apache.river.api.util.Startable;
-
-import com.sun.jini.thread.InterruptedStatusThread;
-import com.sun.jini.thread.ReadersWriter;
-import com.sun.jini.thread.ReadersWriter.ConcurrentLockException;
-import com.sun.jini.thread.ReadyState;
-
-import net.jini.activation.ActivationExporter;
-import net.jini.activation.ActivationGroup;
-import net.jini.config.Configuration;
-import net.jini.config.ConfigurationProvider;
-import net.jini.config.ConfigurationException;
-import net.jini.config.NoSuchEntryException;
-
-import net.jini.discovery.DiscoveryEvent;
-import net.jini.discovery.DiscoveryChangeListener;
-import net.jini.discovery.DiscoveryGroupManagement;
-import net.jini.discovery.DiscoveryLocatorManagement;
-import net.jini.discovery.DiscoveryManagement;
-import net.jini.discovery.LookupDiscoveryManager;
-import net.jini.discovery.LookupDiscoveryRegistration;
-import net.jini.discovery.RemoteDiscoveryEvent;
-
-import net.jini.export.Exporter;
-import net.jini.export.ProxyAccessor;
-
-import net.jini.id.Uuid;
-import net.jini.id.UuidFactory;
-
-import net.jini.jeri.BasicILFactory;
-import net.jini.jeri.BasicJeriExporter;
-import net.jini.jeri.InvocationLayerFactory;
-import net.jini.jeri.ServerEndpoint;
-import net.jini.jeri.tcp.TcpServerEndpoint;
-
-import net.jini.lookup.JoinManager;
-import net.jini.lookup.entry.Comment;
-import net.jini.lookup.entry.ServiceInfo;
-import net.jini.lookup.entry.Status;
-import net.jini.lookup.entry.StatusType;
-
-import net.jini.security.BasicProxyPreparer;
-import net.jini.security.ProxyPreparer;
-import net.jini.security.TrustVerifier;
-import net.jini.security.proxytrust.ServerProxyTrust;
-import net.jini.security.proxytrust.TrustEquivalence;
-
-import net.jini.core.discovery.LookupLocator;
-import net.jini.core.entry.Entry;
-import net.jini.core.event.EventRegistration;
-import net.jini.core.event.RemoteEventListener;
-import net.jini.core.lease.Lease;
-import net.jini.core.lease.UnknownLeaseException;
-import net.jini.core.lookup.ServiceID;
-import net.jini.core.lookup.ServiceRegistrar;
-
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-
-import java.lang.reflect.Array;
-
-import java.net.InetAddress;
-
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.OutputStream;
-import java.io.Serializable;
-
-import java.rmi.activation.ActivationException;
-import java.rmi.activation.ActivationID;
-import java.rmi.activation.ActivationSystem;
-import java.rmi.MarshalledObject;
-import java.rmi.NoSuchObjectException;
-import java.rmi.RemoteException;
-import java.rmi.server.ExportException;
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-
-import java.security.PrivilegedExceptionAction;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Condition;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import net.jini.io.MarshalledInstance;
-
-/**
- * This class is the server side of an implementation of the lookup
- * discovery service. Multiple client-side proxy classes are used to
- * interact and communicate with this backend server. Those proxy
- * classes are: <code>FiddlerProxy</code> (the proxy for the
- * <code>LookupDiscoveryService</code> interface which defines how clients
- * register with the lookup discovery service), <code>FiddlerAdminProxy</code>
- * (the proxy for the <code>FiddlerAdmin</code> interface which specifies
- * the methods through which administration duties such as joining, persistent
- * state logging policy, and shutting down the lookup discovery service can
- * be performed), and <code>FiddlerRegistration</code> (the proxy for the
- * <code>LookupDiscoveryRegistration</code> interface which defines the
- * methods through which clients can perform duties such as group and
- * locator management, state retrieval, and discarding discovered but
- * unavailable lookup services so they are eligible for re-discovery).
- * <p>
- * It is through the proxies that communicate with this class that clients
- * interact with the lookup discovery service. When a client makes a method
- * invocation on one of the proxies, the proxy makes a corresponding call
- * on the methods specified in the <code>Fiddler</code> interface which
- * are implemented in this class, ultimately executing on the backend server.
- * <p>
- *
- * @com.sun.jini.impl
- *
- * This implementation of the lookup discovery service employs a number of
- * {@link java.util.logging.Logger}s. The details of each such
- * {@link java.util.logging.Logger} are described
- * <a href="./package-summary.html#fiddlerLoggers">here</a>.
- * <p>
- * The configuration entries supported by this implementation are described
- * <a href="./package-summary.html#fiddlerConfigEntries">here</a>.
- *
- * @author Sun Microsystems, Inc.
- */
-class FiddlerImpl implements ServerProxyTrust, ProxyAccessor, Fiddler, Startable {
-
- /* Name of this component; used in config entry retrieval and the logger.*/
- static final String COMPONENT_NAME = "com.sun.jini.fiddler";
- /* Loggers used by this implementation of the service. */
- static final Logger problemLogger = Logger.getLogger(COMPONENT_NAME+
- ".problem");
- static final Logger startupLogger = Logger.getLogger(COMPONENT_NAME+
- ".startup");
- static final Logger tasksLogger = Logger.getLogger(COMPONENT_NAME+
- ".tasks");
- static final Logger eventsLogger = Logger.getLogger(COMPONENT_NAME+
- ".events");
- static final Logger groupsLogger = Logger.getLogger(COMPONENT_NAME+
- ".groups");
- static final Logger locatorsLogger = Logger.getLogger(COMPONENT_NAME+
- ".locators");
- static final Logger discardLogger = Logger.getLogger(COMPONENT_NAME+
- ".discard");
- static final Logger leaseLogger = Logger.getLogger(COMPONENT_NAME+
- ".lease");
- static final Logger registrationLogger = Logger.getLogger(COMPONENT_NAME+
- ".registration");
- static final Logger persistLogger = Logger.getLogger(COMPONENT_NAME+
- ".persist");
- /** Data structure - associated with a <code>ServiceRegistrar</code> -
- * containing the <code>LookupLocator</code> and the member groups of
- * the registrar
- */
- static final class LocatorGroupsStruct {
- final LookupLocator locator;
- final String[] groups;
- LocatorGroupsStruct(LookupLocator locator, String[] groups) {
- this.locator = locator;
- this.groups = groups;
- }
- }//end class LocatorGroupsStruct
-
- /* ServiceInfo values */
- private static final String PRODUCT = "Lookup Discovery Service";
- private static final String MANUFACTURER = "Sun Microsystems, Inc.";
- private static final String VENDOR = MANUFACTURER;
- private static final String VERSION = VersionConstants.SERVER_VERSION;
-
- /** When re-setting the bound on lease durations, that bound cannot be
- * set to a value larger than this value */
- static final long MAX_LEASE = 1000L * 60 * 60 * 24 * 365 * 1000;
- /** Log format version */
- private static final int LOG_VERSION = 2;
-
- /** The outer (smart) proxy to this server */
- private FiddlerProxy outerProxy;
- /** The inner proxy (stub or dynamic proxy) to this server */
- private Fiddler innerProxy;
- /** The admin proxy to this server */
- private FiddlerAdminProxy adminProxy;
- /** The service ID associated with this service when it is registered
- * with any lookup service.
- */
- private ServiceID serviceID = null;
- /** The activation id of the current instance of the lookup discovery
- * service, if it happens to be and activatable instance
- */
- private final ActivationID activationID;
- /* Holds the prepared proxy to the ActivationSystem */
- private final ActivationSystem activationSystem;
- /** The unique identifier generated (or recovered) when an instance of
- * this service is constructed. This ID is typically used to determine
- * equality between the proxies of any two instances of this service.
- */
- private Uuid proxyID = null;
- /** Map from the set of all currently discovered registrars to their
- * corresponding [locator,member groups] pairs (locatorGroupsStuct).
- */
- private final HashMap allDiscoveredRegs = new HashMap(11);
- /** Map from registrationID to registrationInfo. Every registration is in
- * this map under its registrationID.
- */
- private final HashMap registrationByID = new HashMap(11);
- /** Map from registrationInfo to registrationInfo (that is, to itself),
- * where the elements of the map are ordered by lease expiration time.
- */
- private final TreeMap registrationByTime = new TreeMap();
- /** Performs all group and locator discovery on behalf of clients */
- private final LookupDiscoveryManager discoveryMgr;
- /** The listener registered for both group discovery events and locator
- * discovery events.
- */
- private final LookupDiscoveryListener discoveryListener
- = new LookupDiscoveryListener();
- /** For each registration created by the lookup discovery service, an
- * event identifier that uniquely maps the registration to the
- * registration's listener and managed sets will be generated and
- * associated with the registration through the EventRegistration
- * field of the registrationInfo. This event ID is unique across
- * all registrations with the current instance of the lookup discovery
- * service.
- */
- private long curEventID = 0;
- /** Earliest expiration time over all active registrations */
- private long minExpiration = Long.MAX_VALUE;
- /** The lookup discovery manager this service's join manager will use */
- private final DiscoveryManagement joinMgrLDM;
- /** Manager for discovering and registering with lookup services */
- private JoinManager joinMgr;
- /** Executor for sending remote discovery events */
- private final ExecutorService executorService;
- /** Registration lease expiration thread */
- private final LeaseExpireThread leaseExpireThread;
- /** Snapshot-taking thread */
- private final SnapshotThread snapshotThread;
-
- /** Concurrent object to control read and write access */
- private final ReadersWriter concurrentObj = new ReadersWriter();
- /** Object for synchronizing with the registration expire thread */
- private final Condition leaseExpireThreadSyncObj;
- /** Object on which the snapshot-taking thread will synchronize */
- private final Condition snapshotThreadSyncObj;
-
- /** Reliable log object to hold persistent state of the service.
- * This object is also used as a flag: non-null ==> persistent service
- * null ==> non-persistent service
- */
- private final ReliableLog log;
- /** Flag indicating whether system is in a state of recovery */
- private boolean inRecovery;
- /** Current number of records in the Log File since the last snapshot */
- private int logFileSize = 0;
- /** The name of the directory to which the persistent modes of this service
- * will log the service's state (using ReliableLog).
- */
- private final String persistDir;
- /** least upper bound applied to all granted lease durations */
- private long leaseBound = 1000 * 60 * 30;
- /** Weight factor applied to snapshotSize when deciding to take snapshot */
- private float snapshotWt = 10;
- /** Log File must contain this many records before snapshot allowed */
- private int snapshotThresh = 200;
- /** Groups whose members are lookup services this service should join.
- * Unless configured otherwise, this service will initially join the
- * un-named public group. The desired join groups for this service can
- * be set administratively after start up.
- */
- private String[] thisServicesGroups = new String[] {""};
- /** Locators of specific lookup services this service should join.
- * This service will initially join no lookups found through locator
- * discovery. The locators of the specific lookup services that are
- * desired for this service to join should be set administratively
- * after start up.
- */
- private LookupLocator[] thisServicesLocators = {};
- /** The attributes to use when joining lookup service(s) */
- private Entry[] thisServicesAttrs
- = new Entry[]
- { new ServiceInfo(PRODUCT,MANUFACTURER,VENDOR,VERSION,"",""),
- new BasicServiceType("Lookup Discovery Service")
- };
- /* Object used to obtain the configuration items for this service. */
- private Configuration config;
- /* The JAAS login context to use when performing a JAAS login. */
- private final LoginContext loginContext;
- /* The exporter used to export this service. */
- private final Exporter serverExporter;
- /* Maximum value of upper bound on lease durations.*/
- private final long leaseMax;
- /* Flag indicating this service is being started for the very 1st time */
- private boolean initialStartup = true;
- /** Object that, if non-<code>null</code>, will cause the object's
- * <code>unregister</code> method to be invoked during service shutdown
- * to notify the service starter framework that the reference to this
- * service's implementation can be 'released' for garbage collection;
- * the framework is notified that it does not have to hold on to the
- * service reference any longer. Note hat this object is used only
- * in the non-activatable case.
- */
- private final LifeCycle lifeCycle;
-
- /* ProxyPreparer fields were originally static and set every time a
- * constructor was called, this was done to enable the static class
- * RegistrationInfo to prepare recovered proxy's after deserialization.
- *
- * These fields are now final instance fields. This would for instance
- * enable multiple FiddlerImpl to co exist in one jvm if necessary using
- * different configurations.
- */
- /* Preparer for proxies to remote listeners newly registered with this
- * service.
- */
- private final ProxyPreparer listenerPreparer;
- /* Preparer for proxies to remote listeners, previously prepared, and
- * recovered from this service's persisted state.
- */
- private final ProxyPreparer recoveredListenerPreparer;
- /* Preparer for initial and new lookup locators this service should
- * discover and join.
- */
- private final ProxyPreparer locatorToJoinPreparer;
- /* Preparer for lookup locators this service should discover and join
- * that were previously prepared and which were recovered from this
- * service's persisted state.
- */
- private final ProxyPreparer recoveredLocatorToJoinPreparer;
- /* Preparer for initial and new lookup locators this service should
- * discover on behalf of the clients that register with it.
- */
- private final ProxyPreparer locatorToDiscoverPreparer;
- /* Preparer for lookup locators this service should discover on behalf
- * of its registered clients that were previously prepared and which
- * were recovered from this service's persisted state.
- */
- private final ProxyPreparer recoveredLocatorToDiscoverPreparer;
- /** Object used to prevent access to this service during the service's
- * initialization or shutdown processing.
- */
- private final ReadyState readyState = new ReadyState();
-
- private boolean persistent;
- private LocalLogHandler logHandler;
- private AccessControlContext context;
-
- private boolean started;
-
- /* ************************* BEGIN Constructors ************************ */
- /**
- * Constructs a new instance of FiddlerImpl. This version of the
- * constructor is used to create an activatable instance of the lookup
- * discovery service that logs its state information to persistent storage.
- * <p>
- * A constructor having this signature is required for the class to be
- * activatable. This constructor is automatically called by the
- * activation group when the lookup discovery service is activated.
- *
- * @param activationID the activation ID generated by the activation
- * system and assigned to the instance of the server
- * being activated
- * @param data state data (represented as a
- * <code>MarshalledObject</code>) which is needed to
- * re-activate this server
- *
- * @throws IOException this exception can occur when there is
- * a problem recovering data from disk,
- * exporting the server that's being
- * activated, or when unmarshalling the
- * given <code>data</code> parameter.
- * @throws ConfigurationException this exception can occur when a
- * problem occurs while retrieving an item
- * from the <code>Configuration</code>
- * generated from the contents of the
- * given <code>data</code> parameter
- * @throws ActivationException this exception can occur when a problem
- * occurs while activating the service
- * @throws LoginException this exception occurs when authentication
- * fails while performing a JAAS login for
- * this service
- * @throws ClassNotFoundException this exception can occur while
- * unmarshalling the given <code>data</code>
- * parameter; when a class needed in the
- * unmarshalling process cannot be found.
- * @throws ClassCastException this exception can occur while
- * unmarshalling the given <code>data</code>
- * parameter; when the contents of that
- * parameter is not a <code>String</code>
- * array.
- */
- FiddlerImpl(ActivationID activationID,
- MarshalledObject data) throws IOException,
- ActivationException,
- ConfigurationException,
- LoginException,
- ClassNotFoundException
- {
- this(init( (String[]) new MarshalledInstance(data).get(false), true /* persistent */, activationID ), null);
- }//end activatable constructor
-
- /**
- * Constructs a new instance of FiddlerImpl. This version of the
- * constructor is used to create a NON-activatable instance of the
- * lookup discovery service.
- *
- * @param configArgs <code>String</code> array whose elements are
- * the arguments to use when creating this version of
- * the server
- * @param lifeCycle instance of <code>LifeCycle</code> that, if
- * non-<code>null</code>, will cause this object's
- * <code>unregister</code> method to be invoked during
- * shutdown to notify the service starter framework that
- * the reference to this service's implementation can be
- * 'released' for garbage collection. A value of
- * <code>null</code> for this argument is allowed.
- * @param persistent if <code>true</code>, then the service should persist
- * its state.
- *
- * @throws IOException this exception can occur when there is
- * a problem recovering data from disk, or
- * while exporting the server that's being
- * created.
- * @throws ConfigurationException this exception can occur when an
- * problem occurs while retrieving an item
- * from the <code>Configuration</code>
- * generated from the contents of the
- * given <code>configArgs</code> parameter
- * @throws LoginException this exception occurs when authentication
- * fails while performing a JAAS login for
- * this service
- */
- FiddlerImpl(String[] configArgs, LifeCycle lifeCycle, boolean persistent)
- throws IOException,
- ConfigurationException,
- LoginException
- {
- this(init(configArgs, persistent), lifeCycle);
- }//end non-activatable constructor
-
- FiddlerImpl(FiddlerInit i, LifeCycle lifeCycle){
- this.snapshotThreadSyncObj = concurrentObj.newCondition();
- this.leaseExpireThreadSyncObj = concurrentObj.newCondition();
- this.lifeCycle = lifeCycle;
- discoveryMgr = i.discoveryMgr;
- listenerPreparer = i.listenerPreparer;
- locatorToJoinPreparer = i.locatorToJoinPreparer;
- locatorToDiscoverPreparer = i.locatorToDiscoverPreparer;
- recoveredListenerPreparer = i.recoveredListenerPreparer;
- recoveredLocatorToJoinPreparer = i.recoveredLocatorToJoinPreparer;
- recoveredLocatorToDiscoverPreparer = i.recoveredLocatorToDiscoverPreparer;
- persistDir = i.persistDir;
- log = i.log;
- joinMgrLDM = i.joinMgrLDM;
- leaseMax = i.leaseMax;
- executorService = i.executorService;
- activationSystem = i.activationSystem;
- serverExporter = i.serverExporter;
- logHandler = i.logHandler;
- activationID = i.activationID;
- // These three fields are used by the Starter.start() implementation.
- persistent = i.persistent;
- config = i.config;
- context = i.context;
- loginContext = i.loginContext;
- leaseExpireThread = AccessController.doPrivileged(
- new PrivilegedAction<LeaseExpireThread>(){
- @Override
- public LeaseExpireThread run() {
- return new LeaseExpireThread(FiddlerImpl.this);
- }
-
- }, context);
- if (log != null){
- snapshotThread = AccessController.doPrivileged(
- new PrivilegedAction<SnapshotThread>(){
- @Override
- public SnapshotThread run() {
- return new SnapshotThread(FiddlerImpl.this);
- }
-
- }, context);
- } else {
- snapshotThread = null;
- }
- }
- /* ************************** END Constructors ************************* */
-
- /* ******************* BEGIN Inner Class Definitions ******************* */
- /** Class which is used to communicate the status of this service to
- * interested entities. In particular, when certain errors occur during
- * operation, an instance of this class will be registered as an
- * attribute in all of the lookup services with which this service
- * is registered. By registering for notification (from the lookup
- * services) of the existence of this attribute, interested entities
- * such as administrative clients and clients wishing to use this
- * service will be informed when this service can not proceed with its
- * processing, and can take appropriate action.
- */
- private static class FiddlerStatus extends Status {
- private static final long serialVersionUID = -8511826097053446749L;
- public FiddlerStatus(StatusType severity) {
- super(severity);
- }
- }//end class FiddlerStatus
-
- /** Class whose discovered() method is invoked by threads in the
- * LookupDiscovery class whenever a new lookup service is discovered
- * on behalf of a client registration
- */
- private class LookupDiscoveryListener implements DiscoveryChangeListener {
- public LookupDiscoveryListener() {
- super();
- }
- public void discovered(DiscoveryEvent event) {
- executorService.execute(new DiscoveredEventTask(event));
- }
- public void discarded(DiscoveryEvent event) {
- executorService.execute(new DiscardedEventTask(event));
- }
- public void changed(DiscoveryEvent event) {
- executorService.execute(new ChangedEventTask(event));
- }
- }//end class LookupDiscoveryListener
-
- /** This class acts as a record of one registration with the lookup
- * discovery service; containing all of the information about that
- * registration.
- */
- private final static class RegistrationInfo
- implements Comparable, Serializable
- {
- private static final long serialVersionUID = 2L;
-
- /** The unique identifier assigned to the registration to which the
- * data in the current implementation of this class corresponds.
- * This identifier is unique across all other active registrations
- * generated with the current instance of the lookup discovery
- * service.
- * @serial
- */
- public final Uuid registrationID;
- /** Map from the set of instances of the <code>ServiceRegistrar</code>
- * interface, to the set of marshalled instances of the
- * <code>ServiceRegistrar</code> interface, where each key and
- * each value (which is the marshalled form of its corresponding
- * key) is a proxy to one of the lookup service(s) that have been
- * discovered for the current registration. The contents of
- * this set represents the 'remote state' of the registration's
- * currently discovered lookup service(s).
- * @serial
- */
- public final HashMap discoveredRegsMap;
- /** The managed set containing the names of the groups whose
- * members are the lookup services the lookup discovery service
- * should attempt to discover for the current registration.
- * (HashSet is used to prevent duplicates.)
- * @serial
- */
- public HashSet<String> groups;
- /** The managed set containing the locators of the specific lookup
- * services the lookup discovery service should attempt to discover
- * for the current registration. (HashSet is used to prevent
- * duplicates.)
- * @serial
- */
- public HashSet locators;
- /** The ID of the lease placed on the current registration.
- * @serial
- */
- public final Uuid leaseID;
- /** The absolute expiration time of the current lease.
- * @serial
- */
- public long leaseExpiration;
- /** The identifier that maps the current registration to the remote
- * event listener and the managed set of groups and locators.
- */
- public long eventID;
- /** The current sequence number of the set of remote discovery events
- * sent to the current registration's listener. When a registration
- * is granted, this class is instantiated to contain the information
- * related to that particular registration. The event sequence
- * number is initialized to 0 upon instantiation because the
- * remote discovery events are sent to the listeners of each
- * separate registration. Thus, each registration has its own
- * sequence of events.
- * @serial
- */
- public long seqNum;
- /** The handback object returned with every remote discovery event
- * sent to the current registration's listener.
- * @serial
- */
- public final MarshalledObject handback;
- /** When the lookup discovery service discards a registrar as a
- * result of some internal condition (such as multicast announcements
- * ceasing) and not as a result of a request from a registration,
- * every registration configured for group discovery of that discarded
- * registrar will be sent a remote discarded event. On the other
- * hand, for the case where a registrar is discarded as a result
- * of a request from a registration, only those registrations that
- * actually request that the registrar be discarded will be sent
- * a remote discarded event. This flag is used to determine whether
- * to send a remote discarded event to one or multiple listeners.
- */
- public boolean discardFlag;
- /** The remote event listener registered by the client. This field
- * is transient because it is marshalled separately from the rest
- * of this class when being serialized. (See the description for
- * <code>writeObject</code> below.)
- */
- public transient RemoteEventListener listener;
-
- /** Constructs an instance of this class and stores the information
- * related to the current registration: IDs, managed sets, lease
- * information, and event registration information.
- */
- public RegistrationInfo(Uuid registrationID,
- String[] groups,
- LookupLocator[] locators,
- Uuid leaseID,
- long leaseExpiration,
- long eventID,
- MarshalledObject handback,
- RemoteEventListener listener)
- {
- this.registrationID = registrationID;
- /* Initialize the groups field, removing nulls and duplicates */
- if(groups != null) {
- this.groups = new HashSet<String>();
- for(int i=0;i<groups.length;i++) {
- if(groups[i] == null) continue;
- this.groups.add(groups[i]);
- }
- }
- /* Initialize the locators field, removing nulls and duplicates */
- this.locators = new HashSet();
- if( (locators != null) && (locators.length > 0) ) {
- for(int i=0;i<locators.length;i++) {
- if(locators[i] == null) continue;
- this.locators.add(locators[i]);
- }
- }
- this.discoveredRegsMap = new HashMap(11);
- this.leaseID = leaseID;
- this.leaseExpiration = leaseExpiration;
-
- this.eventID = eventID;
- this.seqNum = 0; // initialize to 0
- this.handback = handback;
- this.discardFlag = false;//set true only on first discard request
- this.listener = listener;
- }//end constructor
-
- /** Attempts to marshal each element of the input set of instances of
- * the <code>ServiceRegistrar</code> interface and then map the
- * registrar to its marshalled form, and store the mapping in this
- * registration's <code>discoveredRegsMap</code> field.
- * <p>
- * This method is typically invoked to handle discovered (as opposed
- * to discarded) registrars. Note that if a particular registrar
- * cannot be serialized (marshalled), it is not included in the
- * mapping; nor is it included in the return set.
- *
- * @param regMapIn mapping in which the key values are the registrars
- * to serialize and store, and the map values are data
- * structures of type <code>LocatorGroupsStruct</code>
- * that contain the locator and member groups of the
- * corresponding registrar key
- *
- * @return a <code>HashMap</code> whose keys are the registrars
- * whose marshalled form and un-marshalled form were inserted
- * as key/value pairs into the <code>discoveredRegsMap</code>
- * field of this regInfo; and whose values are the member
- * groups of each corresponding registrar key.
- */
- public HashMap addToDiscoveredRegs(HashMap regMapIn) {
- HashMap regMapOut = new HashMap(regMapIn.size());
- Iterator itr = (regMapIn.entrySet()).iterator();
- nextReg:
- for(int i=0;itr.hasNext();i++) {
- Map.Entry pair = (Map.Entry)itr.next();
- ServiceRegistrar reg = (ServiceRegistrar)pair.getKey();
- /* If reg is already in map, go to next registrar */
- if( discoveredRegsMap.containsKey(reg) ) continue nextReg;
- /* It doesn't contain it, try to marshal it */
- MarshalledObject mReg = null;
- try {
- mReg = new MarshalledInstance(reg).convertToMarshalledObject();
- } catch(IOException e) { continue nextReg; } //failed, next reg
- /* Succeeded, map registrar to its marshalled form */
- discoveredRegsMap.put(reg,mReg);
- /* Map the registrar to its member groups for the return map */
- regMapOut.put(reg,
- ((LocatorGroupsStruct)pair.getValue()).groups);
- }//end loop
- return regMapOut;
- }//end addToDiscoveredRegs
-
- /** Performs a primary sort by leaseExpiration, and a secondary sort
- * by registrationID. The secondary sort is immaterial, except to
- * ensure a total order (required by <code>TreeMap</code>).
- */
- public int compareTo(Object obj) {
- RegistrationInfo regInfo = (RegistrationInfo)obj;
- if (this == regInfo) return 0;
- if ( (leaseExpiration < regInfo.leaseExpiration)
- || ( (leaseExpiration == regInfo.leaseExpiration)
- && (eventID < regInfo.eventID) ) )
- {
- return -1;
- }//endif
- return 1;
- }//end compareTo
-
- /** When a registration is granted to a client, the client registers
- * a remote listener with the lookup discovery service so that the
- * lookup discovery service may send remote discovery events to the
- * client. The client typically annotates the listener with an RMI
- * codebase from which the backend server can download the remote
- * listener's proxy (stub). When the current registration is logged
- * to persistent storage (for example, a snapshot is taken), the
- * listener is written to the output snapshot or log file through
- * an <code>ObjectOutputStream</code> which only serializes the
- * listener; it does not marshal the listener. Thus, when the
- * listener field of this class is logged, unless special action
- * is taken, the codebase from which to retrieve the listener will
- * not be included in the output.
- *
- * In order to include the codebase with the listener when saving
- * state, the following custom <code>writeObject</code> method
- * is provided which first serializes the current instance of
- * this class (excluding the transient <code>listener</code> field),
- * and then explicitly marshals the listener to preserve the
- * codebase upon writing to the file. In this way, the listener --
- * along with its codebase -- is persisted through a mechanism that
- * is separate from the normal mechanism applied to the remaining
- * fields of this class.
- */
- private void writeObject(ObjectOutputStream stream) throws IOException{
- stream.defaultWriteObject();
- stream.writeObject(new MarshalledInstance(listener).convertToMarshalledObject());
- }//end writeObject
-
- /** When this class is deserialized, this method is invoked. This
- * method first deserializes the non-transient elements of this
- * class, and then unmarshals the remote event listener. (See the
- * description for <code>writeObject</code> above.)
- */
- private void readObject(ObjectInputStream stream)
- throws IOException, ClassNotFoundException
- {
- stream.defaultReadObject();
- MarshalledObject mo = (MarshalledObject)stream.readObject();
- try {
- listener = (RemoteEventListener) new MarshalledInstance(mo).get(false);
- } catch (Throwable e) {
- problemLogger.log(Level.INFO, "problem recovering listener "
- +"for recovered registration", e);
- if((e instanceof Error) && (ThrowableConstants.retryable(e)
- == ThrowableConstants.BAD_OBJECT))
- {
- throw (Error)e;
- }//endif
- }
- }//end readObject
-
- /**
- * Must be called immediately after de-serialization to prepare
- * proxies.
- *
- * @param recoveredListenerPreparer
- * @param recoveredLocatorToDiscoverPreparer
- */
- public void prepare(ProxyPreparer recoveredListenerPreparer,
- ProxyPreparer recoveredLocatorToDiscoverPreparer )
- {
- try {
- /* Re-prepare the recovered listener */
- listener = (RemoteEventListener)
- recoveredListenerPreparer.prepareProxy(listener);
- } catch (Throwable e) {
- problemLogger.log(Level.INFO, "problem recovering listener "
- +"for recovered registration", e);
- if((e instanceof Error) && (ThrowableConstants.retryable(e)
- == ThrowableConstants.BAD_OBJECT))
- {
- throw (Error)e;
- }//endif
- }
-
- /* Prepare the locators recovered from the stream */
- int nUnprepared = (locators).size();
- locators = (HashSet)prepareOldLocators
- ( recoveredLocatorToDiscoverPreparer,
- locators );
- if( nUnprepared != (locators).size() ) {
- /* Failure occurred when preparing one of the locs. Because
- * this breaks the contract with the client, this registration
- * will not be recovered so that the client will eventually
- * be notified. To facilitate this, the listener is set to
- * null so that the registration will not be added to the
- * managed set, and so that when the client eventually attempts
- * to renew the lease on that registration, an exception will
- * occur; causing the client to be "notified" that there was
- * a problem with that registration. The client can then
- * retry the registration; and if problems still exist, the
- * exception the client receives may give the client more
- * useful information from which the client can determine
- * how to proceed.
- */
- listener = null;
- if( problemLogger.isLoggable(Level.WARNING) ) {
- problemLogger.log(Level.WARNING, "failure preparing "
- +"locator while recovering registration"
- +"... discarding recovered"
- +"registration");
- }//endif
- }
- }
-
- }//end class RegistrationInfo
-
- /** This class represents a <code>Task</code> object that is placed
- * in the <code>TaskManager</code> queue for processing in the thread
- * pool. Instances of this class are placed on the task queue when
- * registrations are granted.
- * <p>
- * The <code>run</code> method of this class will determine if any of
- * the new registration's desired lookup service(s) have already been
- * discovered, and will send the appropriate remote discovery event to
- * the registration's listener.
- */
- private final class NewRegistrationTask implements Runnable {
- /** The data structure record corresponding to the new registration */
- public final RegistrationInfo regInfo;
- /** Constructs an instance of this class and stores the registration
- * information.
- */
- public NewRegistrationTask(RegistrationInfo regInfo) {
- this.regInfo = regInfo;
- }//end constructor
- /** This method processes the information associated with the new
- * registration and determines, based on the current state of the
- * set of 'already-discovered' lookup service(s), whether to send
- * a <code>RemoteDiscoveryEvent</code> to the new registration's
- * listener.
- */
- public void run() {
- concurrentObj.writeLock();
- try {
- logInfoTasks("NewRegistrationTask.run(): "
- +"new Registration added");
- maybeSendDiscoveredEvent(regInfo,allDiscoveredRegs);
- } finally {
- concurrentObj.writeUnlock();
- }
- }//end run
-
- }//end class NewRegistrationTask
-
- /** This class represents a <code>Task</code> object that is placed
- * in the <code>TaskManager</code> queue for processing in the thread
- * pool. An instance of this class is placed on the task queue when a
- * <code>DiscoveryEvent</code> instance indicating a discovered event
- * is received from the local discovery process.
- * <p>
- * The <code>run</code> method of this class will process discovery
- * event information and determine to which active registrations the
- * appropriate <code>RemoteDiscoveryEvent</code> should be sent; and
- * then sends that event.
- */
- private final class DiscoveredEventTask implements Runnable {
- /** The local event sent by the discovery manager. */
- public final DiscoveryEvent event;
- /** Constructs an instance of this class and stores the event*/
- public DiscoveredEventTask(DiscoveryEvent event) {
- this.event = event;
- }//end constructor
- /** This method processes the local discovery event information and
- * determines, based on the current state of each active
- * registration, to which such registration the appropriate
- * <code>RemoteDiscoveryEvent</code> should be sent. After making
- * the determination, the remote event appropriate for each
- * registration is constructed and sent.
- */
- public void run() {
- /* Get locators before sync block (no remote calls in sync block)*/
- Map groupsMap = event.getGroups();
- ServiceRegistrar[] regs = event.getRegistrars();
- HashMap regMap = new HashMap(regs.length);
- for(int i=0;i<regs.length;i++) {
- try {
- LookupLocator regLoc = regs[i].getLocator();
- String[] regGroups = (String[])groupsMap.get(regs[i]);
- LocatorGroupsStruct regLocGroups
- = new LocatorGroupsStruct(regLoc,regGroups);
- regMap.put(regs[i],regLocGroups);
- } catch(Exception e) {
- problemLogger.log(Levels.FAILED,
- "problem retrieving locator "
- +"from discovered lookup service ... "
- +"discarded the lookup service", e);
- discoveryMgr.discard(regs[i]);
- }
- }//end loop
- /* Synchronization block -- no remote calls here */
- concurrentObj.writeLock();
- logInfoTasks("DiscoveredEventTask.run(): processing DISCOVERED "
- +"event from discovery manager");
- try {
- /* Update the global allDiscoveredRegs map with new pairs */
- Set eSet = regMap.entrySet();
- for(Iterator itr = eSet.iterator(); itr.hasNext(); ) {
- Map.Entry pair = (Map.Entry)itr.next();
- allDiscoveredRegs.put(pair.getKey(),pair.getValue());
- }//end loop
- /* Loop thru regInfo's, adding only those not already known */
- for( Iterator itr=registrationByID.values().iterator();
- itr.hasNext(); )
- {
- RegistrationInfo regInfo = (RegistrationInfo)itr.next();
- /* Build and send the "discovered event" if appropriate */
- maybeSendDiscoveredEvent(regInfo,regMap);
- }//end loop
- } finally {
- concurrentObj.writeUnlock();
- }
- }//end run
-
- }//end class DiscoveredEventTask
-
- /** This class represents a <code>Task</code> object that is placed
- * in the <code>TaskManager</code> queue for processing in the thread
- * pool. An instance of this class is placed on the task queue when a
- * <code>DiscoveryEvent</code> instance indicating a discarded event
- * is received from the local discovery process.
- * <p>
- * The <code>run</code> method of this class will process event
- * information resulting from the "discarding" of one or more
- * lookup services (registrars), and will determine to which active
- * registrations the appropriate <code>RemoteDiscoveryEvent</code>
- * should be sent; and then sends that event.
- */
- private final class DiscardedEventTask implements Runnable {
- /** The local event sent by the discovery manager. */
- public final DiscoveryEvent event;
- /** Constructs an instance of this class and stores the event*/
- public DiscardedEventTask(DiscoveryEvent event) {
- this.event = event;
- }//end constructor
- /** This method processes the local discovery event information and
- * determines, based on the current state of each active
- * registration, to which such registration the appropriate
- * <code>RemoteDiscoveryEvent</code> should be sent. After making
- * the determination, the remote event appropriate for each
- * registration is constructed and sent.
- */
- public void run() {
- concurrentObj.writeLock();
- logInfoTasks("DiscardedEventTask.run(): processing DISCARDED "
- +"event from discovery manager");
- try {
- /* Get the registrars that were just discarded */
- Map groupsMap = event.getGroups();
- HashSet allDiscardedRegs = new HashSet(groupsMap.size());
- /* Determine if we're here because of an external request for
- * discard from one of the regInfo's (an active communication
- * discard), or because the discovery manager has determined
- * one or more of the discovered registrars has become
- * unreachable (a passive communication discard)
- */
- RegistrationInfo regInfo = externalDiscardRequest();
- /* If an external request, send the discarded event to only
- * the regInfo that requested the discard; otherwise, send
- * it to all regInfo's that might be interested.
- */
- if(regInfo != null) {
- /* Send discard event to only this one registration */
- HashSet discardedRegs = maybeSendDiscardedEvent
- (regInfo,groupsMap,true);
- /* Transfer the just-discarded regs to the summary set */
- for(Iterator jtr=discardedRegs.iterator();jtr.hasNext(); ){
- allDiscardedRegs.add(jtr.next());
- }
- } else {
- /* Send discard event to each "eligible" registration */
- for( Iterator itr=registrationByID.values().iterator();
- itr.hasNext(); )
- {
- regInfo = (RegistrationInfo)itr.next();
- HashSet discardedRegs = maybeSendDiscardedEvent
- (regInfo,groupsMap,false);
- /* Transfer the just-discarded regs to summary set */
- for(Iterator jtr=discardedRegs.iterator();
- jtr.hasNext(); ) {
- allDiscardedRegs.add(jtr.next());
- }
- }//end loop
- }//endif
- maybeRemoveDiscardedRegsFromGlobalSet(allDiscardedRegs);
- } finally {
- concurrentObj.writeUnlock();
- }
- }//end run
-
- /** This method determines, based on the current state of the
- * <code>regInfo</code> parameter, whether or not to send a
- * remote discarded event to the regInfo's listener, and then builds
- * and sends the event if appropriate. This method is called in
- * response to one of the following situations:
- * <p>
- * 1 after invocation of the public <code>discard</code> method
- * 2 after receipt of a "passive" discarded event from the discovery
- * manager.
- * <p>
- * For case 1, such an event typically indicates what is referred to
- * as an "active, communication" discarded event. This term is used
- * in this situation because the regInfo takes the specific action
- * of requesting that a registrar the client has determined is
- * unreachable be discarded.
- * <p>
- * For case 2, such an event typically indicates what is referred to
- * as a "passive, communication" discarded event. This term is used
- * here because the discovery manager - not the client - has determined
- * that one or more of the previously discovered registrars are now
- * unreachable. In this case, the client remains "passive", and it
- * is the discovery manager that discards the unreachable registrars
- * and notifies the client(s).
- *
- * @param regInfo the data structure record corresponding to the
- * registration whose listener will receive the event
- * @param groupsMap mapping from the registrars referenced in the
- * just-received event to their corresponding set of
- * member groups
- * @param active flag indicating whether the event is an "active"
- * or a "passive" discarded event
- *
- * @return set of registrars that were discarded for the given regInfo
- */
- private HashSet maybeSendDiscardedEvent(RegistrationInfo regInfo,
- Map groupsMap,
- boolean active)
- {
- HashSet discardedRegs = new HashSet(groupsMap.size()); //return val
- /* If no interest in groups or locators, go to next regInfo*/
- if( (regInfo.groups != null) && ((regInfo.groups).size() == 0)
- && ((regInfo.locators).size() == 0) )
- {
- return discardedRegs;
- }
- HashMap discardMap = new HashMap(groupsMap.size());
- /* loop thru the (registrar,groups) pairs, find regs to discard */
- Set eSet = groupsMap.entrySet();
- for(Iterator itr = eSet.iterator(); itr.hasNext(); ) {
- Map.Entry pair = (Map.Entry)itr.next();
- ServiceRegistrar reg = (ServiceRegistrar)pair.getKey();
- /* Include the current reg in the discard map only if that
- * reg is in the regInfo's discovered set.
- */
- if( (regInfo.discoveredRegsMap).containsKey(reg) ) {
- /* The groups corresponding to the discarded registrar that
- * arrived in the event may be more up-to-date than the
- * groups associated with the registrar in the global map.
- * Thus, if the event is a passive communication discarded
- * event, when determining whether the regInfo is still
- * interested in the discarded registrar, use the old group
- * info rather than the group info sent in the event.
- */
- String[] regGroups = (active ? (String[])pair.getValue() :
- ((LocatorGroupsStruct)allDiscoveredRegs.get(reg)).groups );
-
- if( active || interested(regGroups,regInfo.groups) ) {
- discardMap.put(reg,regGroups);
- discardedRegs.add(reg);
- (regInfo.discoveredRegsMap).remove(reg);
- }//end if
- }//end if
- }//end loop
- /* Build and send the "discarded event" */
- RemoteDiscoveryEvent event = buildEvent(regInfo,discardMap,true);
- if(event != null) {
- queueEvent(regInfo,event);
- logInfoEvents("DiscardedEventTask.run(): "
- +"DISCARDED Event SENT to regInfo\n");
- }
- return discardedRegs;
- }//end maybeSendDiscardedEvent
-
- }//end class DiscardedEventTask
-
- /** This class represents a <code>Task</code> object that is placed
- * in the <code>TaskManager</code> queue for processing in the thread
- * pool. Instances of this class are placed on the task queue when
- * registrations request that a given registrar be discarded.
- * <p>
- * The <code>run</code> method of this class will remove the indicated
- * registrar from the registration's set of discovered registrars and
- * if successfully removed, will build and send a remote discarded event
- * to the registration's listener.
- */
- private final class DiscardRegistrarTask implements Runnable {
- /** Data structure record corresponding to the registration that has
- * requested to have one of its discovered registrars discarded
- */
- public final RegistrationInfo regInfo;
- /** The registrar to discard */
- public final ServiceRegistrar registrar;
- /** Constructs an instance of this class and stores the registration
- * information.
- */
- public DiscardRegistrarTask(RegistrationInfo regInfo,
- ServiceRegistrar registrar)
- {
- this.regInfo = regInfo;
- this.registrar = registrar;
- }//end constructor
- /** This method attempts to remove the indicated registrar from
- * the registration's set of discovered registrars. If successful,
- * this method builds and sends a remote discarded event to the
- * registration's listener.
- */
- public void run() {
- concurrentObj.writeLock();
- try {
- logInfoTasks("DiscardRegistrarTask.run(): "
- +"registrar requested to be discarded");
- /* Remove registrar from regInfo's set and send event */
- if( (regInfo.discoveredRegsMap).remove(registrar) != null) {
- HashMap groupsMap = mapRegToGroups(registrar,
- ((LocatorGroupsStruct)allDiscoveredRegs.get(registrar)).groups);
-
- RemoteDiscoveryEvent event = buildEvent
- (regInfo,groupsMap,true);
- if(event != null) {
- queueEvent(regInfo,event);
- logInfoEvents("DiscardRegistrarTask.run(): "
- +"DISCARDED Event was SENT\n");
- }//endif
- maybeRemoveDiscardedRegFromGlobalSet(registrar);
- }
- } finally {
- concurrentObj.writeUnlock();
- }
- }//end run
- }//end class DiscardRegistrarTask
-
- /** This class represents a <code>Task</code> object that is placed
- * in the <code>TaskManager</code> queue for processing in the thread
- * pool. An instance of this class is placed on the task queue when a
- * <code>DiscoveryEvent</code> instance indicating a changed event
- * is received from the local discovery process.
- * <p>
- * The <code>run</code> method of this class will process event
- * information resulting from a change in the state of the member
- * groups of one or more lookup services (registrars). This task
- * analyzes the group information in the event and, based on that
- * information, determines which active registrations are no longer
- * interested in the registrars referenced in the event. A
- * <code>RemoteDiscoveryEvent</code> indicating a discarded event
- * will be sent to each active registration that has lost interest
- * in any of the registrars of the event.
- */
- private final class ChangedEventTask implements Runnable {
- /** The local event sent by the discovery manager. */
- public final DiscoveryEvent event;
- /** Constructs an instance of this class and stores the event*/
- public ChangedEventTask(DiscoveryEvent event) {
- this.event = event;
- }//end constructor
- /** This method processes the local discovery event information and
- * determines, based on the current state of each active
- * registration, to which such registration the appropriate
- * <code>RemoteDiscoveryEvent</code> should be sent. After making
- * the determination, the remote event appropriate for each
- * registration is constructed and sent.
- */
- public void run() {
- concurrentObj.writeLock();
- logInfoTasks("ChangedEventTask.run(): processing CHANGED "
- +"event from discovery manager");
- try {
- Map groupsMap = event.getGroups();
- HashSet allDiscardedRegs = new HashSet(groupsMap.size());
- HashMap locatorMap = new HashMap(groupsMap.size());
- /* Retrieve the locators of each registrar in the event */
- for(Iterator itr = (groupsMap.keySet()).iterator();
- itr.hasNext(); )
- {
- ServiceRegistrar reg = (ServiceRegistrar)itr.next();
- locatorMap.put(reg,
- ((LocatorGroupsStruct)allDiscoveredRegs.get(reg)).locator);
- }//end loop
-
- for( Iterator itr=registrationByID.values().iterator();
- itr.hasNext(); )
- {
- RegistrationInfo regInfo = (RegistrationInfo)itr.next();
- HashSet discardedRegs = maybeSendDiscardedEvent
- (regInfo,groupsMap,locatorMap);
- /* Transfer the just-discarded regs to the summary set */
- for(Iterator jtr=discardedRegs.iterator();jtr.hasNext(); ){
- allDiscardedRegs.add(jtr.next());
- }//end loop
- }//end loop
- maybeRemoveDiscardedRegsFromGlobalSet(allDiscardedRegs);
- updateGroupsInGlobalSet(groupsMap); //replace with new groups
- } finally {
- concurrentObj.writeUnlock();
- }
- }//end run
-
- /** This method determines, based on the current state of the
- * <code>regInfo</code> parameter, whether or not to send a
- * remote discarded event to the regInfo's listener, and then builds
- * and sends the event if appropriate. This method is called in
- * response to the receipt of a changed event from the discovery
- * manager.
- * <p>
- * Such an event may indicate what is referred to as a
- * "passive, no interest" discard; passive because the event
- * resulted from action taken by the discovery manager rather than
- * the client, and no interest because the discovery manager sends
- * such an event when it determines that one or more of the
- * previously discovered registrars - although still reachable -
- * have changed their member groups in such a way that they may
- * now be of no interest to one or more of the client registrations.
- * <p>
- * Note that changed events can be sent for registrars having a
- * locator and member groups that the current regInfo never asked
- * to be discovered. This can happen because some other regInfo
- * asked that the registrar's locator or groups be discovered.
- * <p>
- * If a particular registrar is contained in the discovered set
- * of the given regInfo, then we know that that regInfo must
- * have requested discovery of the registrar (through either
- * locator or group discovery). If the registrar is not contained
- * in that set, then there's no need to proceed with the processing
- * of the registrar since we don't want to send a discarded event
- * to a regInfo that was never interested in that registrar in the
- * first place.
- * <p>
- * If the locator of the registrar is contained in the regInfo's
- * set of locators to discover, then that regInfo is considered
- * "still interested" in the registrar; and so no discarded event
- * is sent to the regInfo.
- * <p>
- * Thus, a discarded event is sent to the given regInfo only
- * if the regInfo is not interested in discovering the registrar
- * through locator discovery, and the registrar's member groups have
- * changed in such a way that it now belongs to groups that
- * the regInfo is not interested in discovering and joining.
- *
- * @param regInfo the data structure record corresponding to the
- * registration whose listener will receive the event
- * @param groupsMap mapping from the registrars referenced in the
- * just-received event to their corresponding set of
- * member groups
- * @param locatorMap mapping from the registrars referenced in the
- * just-received event to their corresponding locator
- *
- * @return the registrars that were discarded for the given regInfo
- */
- private HashSet maybeSendDiscardedEvent(RegistrationInfo regInfo,
- Map groupsMap,
- Map locatorMap)
- {
- /* For each registrar discard candidate, send a discarded event if:
- * The candidate is in the discovered set and
- * a. regInfo is configured for at least group discovery
- * b. candidate is NOT to be discovered by locator discovery
- * c. regInfo is no longer interested in the candidate's groups
- */
- HashSet discardedRegs = new HashSet(groupsMap.size()); //return val
- /* If this regInfo isn't interested in groups, go to next regInfo*/
- if( (regInfo.groups != null) && ((regInfo.groups).size() == 0) )
- {
- return discardedRegs;
- }
- HashMap discardMap = new HashMap(groupsMap.size());
- /* loop thru the (registrar,groups) pairs, find regs to discard */
- Set eSet = groupsMap.entrySet();
- for(Iterator itr = eSet.iterator(); itr.hasNext(); ) {
- Map.Entry pair = (Map.Entry)itr.next();
- ServiceRegistrar reg = (ServiceRegistrar)pair.getKey();
- String[] regGroups = (String[])pair.getValue();
- LookupLocator regLoc = (LookupLocator)locatorMap.get(reg);
- /* Include the current reg in the discard map only if that
- * reg is in the regInfo's discovered set, the regInfo
- * is not interested in discovering the reg through locator
- * discovery, and the reg's member groups have changed in
- * such a way that it now belongs to groups that the regInfo
- * is not interested in discovering and joining.
- */
- if( ( (regInfo.discoveredRegsMap).containsKey(reg) )
- && (!interested(regLoc,regGroups,
- regInfo.locators,regInfo.groups)) )
- {
- discardMap.put(reg,regGroups);
- discardedRegs.add(reg);
- (regInfo.discoveredRegsMap).remove(reg);
- }
- }//end loop
- /* Build and send the "discarded event" */
- RemoteDiscoveryEvent event = buildEvent(regInfo,discardMap,true);
- if(event != null) {
- queueEvent(regInfo,event);
- logInfoEvents("ChangedEventTask.run(): "
- +"DISCARDED Event was SENT\n");
- }//endif
- return discardedRegs;
- }//end maybeSendDiscardedEvent
- }//end class ChangedEventTask
-
- /** This class represents a <code>Task</code> object that is placed
- * in the <code>TaskManager</code> queue for processing in the thread
- * pool. Instances of this class are placed on the task queue when
- * a registration has requested the augmentation of the set of groups
- * that currently will be discovered for it.
- */
- private final class AddGroupsTask implements Runnable {
- /** Data structure record of the registration that made the request */
- public final RegistrationInfo regInfo;
- /** The group set with which to replace the registration's old set */
- public final String[] groups;
- /** Constructs an instance of this class and stores the input */
- public AddGroupsTask(RegistrationInfo regInfo, String[] groups) {
- this.regInfo = regInfo;
- this.groups = groups;
- }//end constructor
- public void run() {
- /* For the regInfo associated with the current instance of this
- * task, do the following:
- * a. in the given regInfo data structure, add the new groups,
- * with duplicates removed, to that regInfo's current set of
- * desired groups
- * b. from the global mapping of all currently discovered
- * registrars to (locator,groups) pairs, retrieve the elements
- * that contain registrars belonging to groups that regInfo
- * should now be interested in as a result of the call to
- * addGroups
- * c. for each registrar-to-(locator,groups) mapping retrieved in
- * b. above, add that mapping to the given regInfo data
- * structure's discovered state (these are the registrars that
- * were previously discovered for OTHER regInfo's, not the
- * current regInfo)
- * d. for each of the registrars previously discovered for other
- * registrations that belong to any of the new groups regInfo
- * is now interested in as a result of the call to addGroups,
- * queue a remote discovery event to be sent to that regInfo's
- * listener
- * e. if any of the new groups regInfo is now interested in as
- * as a result of the call to addGroups were not previously
- * in the local discovery manager's managed set of groups,
- * (and the local discovery manager is currently not configured
- * to discover ALL_GROUPS), add the new groups to the local
- * discovery manager so that when that manager does discover
- * one of those groups in the future, a remote discovered
- * event will be sent to the given regInfo's listener
- */
- concurrentObj.writeLock();
- try {
- HashSet newGroupSet = addRegInfoGroups(regInfo,groups); // a.
- if(newGroupSet.size() > 0) {
- logInfoTasks("AddGroupsTask.run(): adding to the "
- +"registration's groups");
- HashMap discoveredRegs = getDesiredRegsByGroup
- (regInfo); // b.
- HashMap regsAdded = regInfo.addToDiscoveredRegs
- (discoveredRegs); // c.
- RemoteDiscoveryEvent event = buildEvent
- (regInfo,regsAdded,false); // d.
- if(event != null) {
- queueEvent(regInfo,event); // d.
- logInfoEvents("AddGroupsTask.run(): DISCOVERED "
- +"Event was SENT\n");
- }//endif
- updateDiscoveryMgrGroups(); // e.
- }//endif(newGroupSet.size() > 0)
- } finally {
- concurrentObj.writeUnlock();
- }
- }//end run
-
- /** Augments the registration's managed set of groups with the new
- * groups.
- *
- * @return the set of new groups added to regInfo's desired groups
- */
- private HashSet addRegInfoGroups(RegistrationInfo regInfo,
- String[] groups)
- {
- /* Build a HashSet (removes duplicates) from the input groups */
- HashSet newGroupSet = new HashSet(1);
- for(int i=0;i<groups.length;i++) {
- newGroupSet.add(groups[i]);
- }//end loop
- /* If the input set was not empty, add the new groups to the
- * registration's managed set of groups.
- */
- if( newGroupSet.size() > 0 ) {
- (regInfo.groups).addAll(newGroupSet);
- }//endif
- return newGroupSet;
- }//end addRegInfoGroups
-
- }//end class AddGroupsTask
-
- /** This class represents a <code>Task</code> object that is placed
- * in the <code>TaskManager</code> queue for processing in the thread
- * pool. Instances of this class are placed on the task queue when
- * a registration has requested the replacement of the set of groups
- * that currently will be discovered for it.
- */
- private final class SetGroupsTask implements Runnable {
- /** Data structure record of the registration that made the request */
- public final RegistrationInfo regInfo;
- /** The group set with which to replace the registration's old set */
- public final String[] groups;
- /** Constructs an instance of this class and stores the input */
- public SetGroupsTask(RegistrationInfo regInfo, String[] groups) {
- this.regInfo = regInfo;
- this.groups = groups;
- }//end constructor
- public void run() {
- /* For the regInfo associated with the current instance of this
- * task, do the following:
- * a. from the global mapping of all currently discovered
- * registrars to their (locator,groups) pair, retrieve the
- * elements that contain registrars belonging to groups that
- * regInfo was interested in PRIOR to the call to setGroups
- * b. in the given regInfo data structure, replace that regInfo's
- * current set of desired groups with the new set of desired
- * groups that resulted from the call to setGroups
- * c. again from the global mapping of all currently discovered
- * registrars to (locator,groups) pairs, retrieve the elements
- * that contain registrars belonging to groups that regInfo
- * should now be interested in as a result of the call to
- * setGroups
- * d. for each registrar-to-(locator,groups) mapping retrieved in
- * c. above, add that mapping to the given regInfo data
- * structure's state (these are the registrars that were
- * previously discovered for OTHER regInfo's, not the current
- * regInfo)
- * e. for each of the registrars previously discovered for other
- * registrations that belong to any of the new groups regInfo
- * is now interested in as a result of the call to setGroups,
- * queue a remote discovery event to be sent to that regInfo's
- * listener
- * f. from the mapping of already-discovered registrars that
- * regInfo was interested in prior to the call to setGroups
- * (the mapping retrieved in a. above), retrieve the elements
- * that contain registrars belonging to groups that regInfo is
- * no longer interested in due to the call to setGroups
- * g. for each registrar-to-(locator,groups) mapping retrieved in
- * f. above, remove that mapping from the given regInfo data
- * structure's state, and queue a remote discarded event to be
- * sent to that regInfo's listener
- * h. if any of the new groups regInfo is now interested in as
- * as a result of the call to setGroups were not previously
- * in the local discovery manager's managed set of groups,
- * add those groups to that discovery manager so that when
- * that manager does discover one of those groups in the
- * future, a remote discovered event will be sent to the given
- * regInfo's listener
- */
- concurrentObj.writeLock();
- try {
- logInfoTasks("SetGroupsTask.run(): setting the "
- +"registration's groups");
- Map oldDesiredRegs = getDesiredRegsByGroup(regInfo); // a.
- setRegInfoGroups(regInfo,groups); // b.
- HashMap newDesiredRegs = getDesiredRegsByGroup(regInfo); // c.
- HashMap regsAdded = regInfo.addToDiscoveredRegs
- (newDesiredRegs); // d.
- RemoteDiscoveryEvent event = buildEvent
- (regInfo,regsAdded,false); // e.
- if(event != null) {
- queueEvent(regInfo,event); // e.
- logInfoEvents("SetGroupsTask.run(): DISCOVERED "
- +"Event was SENT\n");
- }//endif
- Map discardRegs = getUndesiredRegsByGroup
- (oldDesiredRegs,regInfo); // f.
- for(Iterator itr = (discardRegs.keySet()).iterator();
- itr.hasNext(); )
- {
- (regInfo.discoveredRegsMap).remove(itr.next()); // g.
- }//end loop
- event = buildEvent(regInfo,discardRegs,true); // g.
- if(event != null) {
- queueEvent(regInfo,event); // g.
- logInfoEvents("SetGroupsTask.run(): "
- +"DISCARDED Event was SENT\n");
- }//endif
- updateDiscoveryMgrGroups(); // h.
- } finally {
- concurrentObj.writeUnlock();
- }
- }//end run
-
- /** Replaces the registration's managed set of groups with the new
- * groups (even if the new set of groups is empty -- this just means
- * group discovery will be "turned off" for this registration).
- */
- private void setRegInfoGroups(RegistrationInfo regInfo,
- String[] groups)
- {
- if(groups == DiscoveryGroupManagement.ALL_GROUPS) {
- regInfo.groups = null;
- } else {
- /* Build a HashSet from the input set */
- HashSet newGroups = new HashSet();
- for(int i=0;i<groups.length;i++) {
- newGroups.add(groups[i]);
- }//end loop
- /* Prepare the registration's managed set for replacement */
- if(regInfo.groups == null) {
- regInfo.groups = new HashSet();
- } else {
- (regInfo.groups).clear();
- }//endif
- /* Replace the registration's managed set with the new set */
- (regInfo.groups).addAll(newGroups);
- }//end if (groups == DiscoveryGroupManagement.ALL_GROUPS)
- }//end setRegInfoGroups
- }//end class SetGroupsTask
-
- /** This class represents a <code>Task</code> object that is placed
- * in the <code>TaskManager</code> queue for processing in the thread
- * pool. Instances of this class are placed on the task queue when
- * a registration has requested the removal of a set of groups from
- * the current set of groups to discover for it.
- */
- private final class RemoveGroupsTask implements Runnable {
- /** Data structure record of the registration that made the request */
- public final RegistrationInfo regInfo;
- /** The groups to remove from the registration's old set */
- public final String[] groups;
- /** Constructs an instance of this class and stores the input */
- public RemoveGroupsTask(RegistrationInfo regInfo, String[] groups) {
- this.regInfo = regInfo;
- this.groups = groups;
- }//end constructor
- public void run() {
- concurrentObj.writeLock();
- try {
- if(groups.length == 0) return; // nothing from which to remove
- logInfoTasks("RemoveGroupsTask.run(): removing groups from "
- +"the registration's current group set");
- /* regInfo's discovered regs (by group) previously desired */
- Map oldDesiredRegs = getDesiredRegsByGroup(regInfo);
- /* update regInfo's desired regs */
- removeRegInfoGroups(regInfo,groups);
- /* regInfo's discovered regs (by group) no longer desired */
- Map discardRegs = getUndesiredRegsByGroup(oldDesiredRegs,
- regInfo);
- /* remove regInfo's undesired regs from its discovered map */
- for(Iterator itr = (discardRegs.keySet()).iterator();
- itr.hasNext(); )
- {
- (regInfo.discoveredRegsMap).remove(itr.next());
- }//end loop
- RemoteDiscoveryEvent event = buildEvent
- (regInfo,discardRegs,true);
- if(event != null) {
- queueEvent(regInfo,event);
- logInfoEvents("RemoveGroupsTask.run(): "
- +"DISCARDED Event was SENT\n");
- }//endif
- updateDiscoveryMgrGroups(); // may send more discards
- } finally {
- concurrentObj.writeUnlock();
- }
- }//end run
-
- /** Removes the elements of the given set from the given registration's
- * current set of groups to discover.
- */
- private void removeRegInfoGroups(RegistrationInfo regInfo,
- String[] groups)
- {
- HashSet<String> removeSet = new HashSet<String>();
- int l = groups.length;
- for(int i = 0; i < l; i++) {
- removeSet.add(groups[i]);
- }//end loop
- (regInfo.groups).removeAll(removeSet);
- }//end setRegInfoGroups
-
- }//end class RemoveGroupsTask
-
- /** This class represents a <code>Task</code> object that is placed
- * in the <code>TaskManager</code> queue for processing in the thread
- * pool. Instances of this class are placed on the task queue when
- * a registration has requested the augmentation of the set of locators
- * that currently will be discovered for it.
- */
- private final class AddLocatorsTask implements Runnable {
- /** Data structure record of the registration that made the request */
- public final RegistrationInfo regInfo;
- /** The locator set with which to replace the registration's old set */
- public final LookupLocator[] locators;
- /** Constructs an instance of this class and stores the input */
- public AddLocatorsTask(RegistrationInfo regInfo,
- LookupLocator[] locators)
- {
- this.regInfo = regInfo;
- this.locators = locators;
- }//end constructor
- public void run() {
- /* For the regInfo associated with the current instance of this
- * task, do the following:
- * a. in the given regInfo data structure, add the new locators,
- * with duplicates removed, to that regInfo's current set of
- * desired locators
- * b. from the global mapping of all currently discovered
- * registrars to (locator,groups) pairs, retrieve the elements
- * that contain registrars having locators that regInfo
- * should now be interested in as a result of the call to
- * addLocators
- * c. for each registrar-to-(locator,groups) mapping retrieved in
- * b. above, add that mapping to the given regInfo data
- * structure's discovered state (these are the registrars that
- * were previously discovered for OTHER regInfo's, not the
- * current regInfo)
- * d. for each of the registrars previously discovered for other
- * registrations that have locators equal to any of the new
- * locators regInfo is now interested in as a result of the
- * call to addLocators, queue a remote discovery event to be
- * sent to that regInfo's listener
- * e. if any of the new locators regInfo is now interested in as
- * as a result of the call to addLocators were not previously
- * in the local discovery manager's managed set of locators,
- * add the new locators to the local discovery manager so that
- * when that manager does discover one of those locators in
- * the future, a remote discovered event will be sent to the
- * given regInfo's listener
- */
- concurrentObj.writeLock();
- try {
- HashSet newLocSet = addRegInfoLocators(regInfo,locators);// a.
- if(newLocSet.size() > 0) {
- logInfoTasks("AddLocatorsTask.run(): adding to the "
- +"registration's locators");
- HashMap discoveredRegs = getDesiredRegsByLocator
- (regInfo); // b.
- HashMap regsAdded = regInfo.addToDiscoveredRegs
- (discoveredRegs); // c.
- RemoteDiscoveryEvent event = buildEvent
- (regInfo,regsAdded,false); // d.
- if(event != null) {
- queueEvent(regInfo,event); // d.
- logInfoEvents("AddLocatorsTask.run(): DISCOVERED "
[... 14593 lines stripped ...]