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 2012/11/20 07:57:59 UTC

svn commit: r1411564 - /river/jtsk/trunk/src/com/sun/jini/reggie/RegistrarImpl.java

Author: peter_firmstone
Date: Tue Nov 20 06:57:58 2012
New Revision: 1411564

URL: http://svn.apache.org/viewvc?rev=1411564&view=rev
Log:
Changes to Reggie to improve synchronization issues, not a complete fix, Reggie needs a thorough refactoring to improve encapsulation for easier maintenance.

Modified:
    river/jtsk/trunk/src/com/sun/jini/reggie/RegistrarImpl.java

Modified: river/jtsk/trunk/src/com/sun/jini/reggie/RegistrarImpl.java
URL: http://svn.apache.org/viewvc/river/jtsk/trunk/src/com/sun/jini/reggie/RegistrarImpl.java?rev=1411564&r1=1411563&r2=1411564&view=diff
==============================================================================
--- river/jtsk/trunk/src/com/sun/jini/reggie/RegistrarImpl.java (original)
+++ river/jtsk/trunk/src/com/sun/jini/reggie/RegistrarImpl.java Tue Nov 20 06:57:58 2012
@@ -83,6 +83,7 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
+import java.util.SortedMap;
 import javax.net.ServerSocketFactory;
 import javax.net.SocketFactory;
 import javax.security.auth.Subject;
@@ -175,46 +176,49 @@ class RegistrarImpl implements Registrar
     private static final EntryRep[] emptyAttrs = {};
 
     /** Proxy for myself */
-    private RegistrarProxy proxy;
+    private volatile RegistrarProxy proxy;
     /** Exporter for myself */
-    private Exporter serverExporter;
+    private volatile Exporter serverExporter;
     /** Remote reference for myself */
-    private Registrar myRef;
+    private volatile Registrar myRef;
     /** Our service ID */
-    private ServiceID myServiceID;
+    private volatile ServiceID myServiceID;
     /** Our activation id, or null if not activatable */
-    private ActivationID activationID;
+    private volatile ActivationID activationID;
     /** Associated activation system, or null if not activatable */
-    private ActivationSystem activationSystem;
+    private volatile ActivationSystem activationSystem;
     /** Our LookupLocator */
     private volatile LookupLocator myLocator;
     /** Our login context, for logging out */
-    private LoginContext loginContext;
+    private volatile LoginContext loginContext;
     /** Shutdown callback object, or null if no callback needed */
-    private LifeCycle lifeCycle;
+    private volatile LifeCycle lifeCycle;
 
     /** Unicast socket factories */
-    private ServerSocketFactory serverSocketFactory ;
-    private SocketFactory socketFactory;
+    private volatile ServerSocketFactory serverSocketFactory ;
+    private volatile SocketFactory socketFactory;
 
     /**
      * Map from ServiceID to SvcReg.  Every service is in this map under
      * its serviceID.
      */
-    private final HashMap serviceByID = new HashMap();
+    private final Map<ServiceID,SvcReg> serviceByID 
+            = Collections.synchronizedMap(new HashMap<ServiceID,SvcReg>());
     /**
      * Identity map from SvcReg to SvcReg, ordered by lease expiration.
      * Every service is in this map.
      */
-    private final TreeMap serviceByTime = new TreeMap();
+    private final SortedMap<SvcReg,SvcReg> serviceByTime 
+            = Collections.synchronizedSortedMap(new TreeMap<SvcReg,SvcReg>());
     /**
      * Map from String to HashMap mapping ServiceID to SvcReg.  Every service 
      * is in this map under its types.
      */
-    private final HashMap serviceByTypeName = new HashMap();
+    private final Map<String,Map<ServiceID,SvcReg>> serviceByTypeName 
+            = Collections.synchronizedMap(new HashMap<String,Map<ServiceID,SvcReg>>());
     /**
-     * Map from EntryClass to HashMap[] where each HashMap is a map from
-     * Object (field value) to ArrayList(SvcReg).  The HashMap array has as
+     * Map from EntryClass to Map[] where each Map is a map from
+     * Object (field value) to List(SvcReg).  The Map array has as
      * many elements as the EntryClass has fields (including fields defined
      * by superclasses).  Services are in this map multiple times, once
      * for each field of each entry it has.  The outer map is indexed by the
@@ -223,89 +227,99 @@ class RegistrarImpl implements Registrar
      * this is a small memory hit and is simpler than subtracting off base
      * index values when accessing the arrays.
      */
-    private final HashMap serviceByAttr = new HashMap(23);
+    private final Map<EntryClass,Map<Object,List<SvcReg>>[]> serviceByAttr 
+            = Collections.synchronizedMap(new HashMap<EntryClass,Map<Object,List<SvcReg>>[]>(23));
     /**
      * Map from EntryClass to ArrayList(SvcReg).  Services are in this map
      * multiple times, once for each no-fields entry it has (no fields meaning
      * none of the superclasses have fields either).  The map is indexed by
      * the exact type of the entry.
      */
-    private final HashMap serviceByEmptyAttr = new HashMap(11);
+    private final Map<EntryClass,List<SvcReg>> serviceByEmptyAttr 
+            = Collections.synchronizedMap(new HashMap<EntryClass,List<SvcReg>>(11));
     /** All EntryClasses with non-zero numInstances */
-    private final ArrayList entryClasses = new ArrayList();
+    private final List<EntryClass> entryClasses 
+            = Collections.synchronizedList(new ArrayList<EntryClass>());
     /**
      * Map from Long(eventID) to EventReg.  Every event registration is in
      * this map under its eventID.
      */
-    private final HashMap eventByID = new HashMap(11);
+    private final Map<Long,EventReg> eventByID 
+            = Collections.synchronizedMap(new HashMap<Long,EventReg>(11));
     /**
      * Identity map from EventReg to EventReg, ordered by lease expiration.
      * Every event registration is in this map.
      */
-    private final TreeMap eventByTime = new TreeMap();
+    private final SortedMap<EventReg,EventReg> eventByTime 
+            = Collections.synchronizedSortedMap(new TreeMap<EventReg,EventReg>());
     /**
      * Map from ServiceID to EventReg or EventReg[].  An event
      * registration is in this map if its template matches on (at least)
      * a specific serviceID.
      */
-    private final HashMap subEventByService = new HashMap(11);
+    @SuppressWarnings("unchecked")
+    private final Map subEventByService = Collections.synchronizedMap(new HashMap(11));
     /**
      * Map from Long(eventID) to EventReg.  An event registration is in
      * this map if its template matches on ANY_SERVICE_ID.
      */
-    private final HashMap subEventByID = new HashMap(11);
+    private final Map<Long,EventReg> subEventByID = Collections.synchronizedMap(new HashMap<Long,EventReg>(11));
 
     /** Generator for resource (e.g., registration, lease) Uuids */
-    private UuidGenerator resourceIdGenerator = new UuidGenerator();
+    private volatile UuidGenerator resourceIdGenerator = new UuidGenerator();
     /** Generator for service IDs */
-    private UuidGenerator serviceIdGenerator = resourceIdGenerator;
+    private volatile UuidGenerator serviceIdGenerator = resourceIdGenerator;
     /** Event ID */
-    private long eventID = 0;
+    private volatile long eventID = 0;
     /** Random number generator for use in lookup */
     private final Random random = new Random();
 
     /** Preparer for received remote event listeners */
-    private ProxyPreparer listenerPreparer = new BasicProxyPreparer();
+    private volatile ProxyPreparer listenerPreparer = new BasicProxyPreparer();
     /** Preparer for remote event listeners recovered from state log */
-    private ProxyPreparer recoveredListenerPreparer = listenerPreparer;
+    private volatile ProxyPreparer recoveredListenerPreparer = listenerPreparer;
     /** Preparer for received lookup locators */
-    private ProxyPreparer locatorPreparer = listenerPreparer;
+    private volatile ProxyPreparer locatorPreparer = listenerPreparer;
     /** Preparer for lookup locators recovered from state log */
-    private ProxyPreparer recoveredLocatorPreparer = listenerPreparer;
+    private volatile ProxyPreparer recoveredLocatorPreparer = listenerPreparer;
 
     /** ArrayList of pending EventTasks */
-    private final ArrayList newNotifies = new ArrayList();
+    private final List<EventTask> newNotifies = Collections.synchronizedList(new ArrayList<EventTask>());
 
     /** Current maximum service lease duration granted, in milliseconds. */
-    private long maxServiceLease;
+    private volatile long maxServiceLease;
     /** Current maximum event lease duration granted, in milliseconds. */
-    private long maxEventLease;
+    private volatile long maxEventLease;
     /** Earliest expiration time of a SvcReg */
-    private long minSvcExpiration = Long.MAX_VALUE;
+    private volatile long minSvcExpiration = Long.MAX_VALUE;
     /** Earliest expiration time of an EventReg */
-    private long minEventExpiration = Long.MAX_VALUE;
+    private volatile long minEventExpiration = Long.MAX_VALUE;
 
     /** Manager for discovering other lookup services */
-    private DiscoveryManagement discoer;
+    private volatile DiscoveryManagement discoer;
     /** Manager for joining other lookup services */
-    private JoinManager joiner;
+    private volatile JoinManager joiner;
     /** Task manager for sending events and discovery responses */
-    private TaskManager tasker;
+    private volatile TaskManager tasker;
     /** Service lease expiration thread */
-    private Thread serviceExpirer;
+    private final Thread serviceExpirer;
     /** Event lease expiration thread */
-    private Thread eventExpirer;
+    private final Thread eventExpirer;
     /** Unicast discovery request packet receiving thread */
-    private UnicastThread unicaster;
+    private volatile UnicastThread unicaster;
     /** Multicast discovery request packet receiving thread */
-    private Thread multicaster;
+    private final Thread multicaster;
     /** Multicast discovery announcement sending thread */
-    private Thread announcer;
+    private final Thread announcer;
     /** Snapshot-taking thread */
-    private Thread snapshotter;
+    private final Thread snapshotter;
 
     /** Concurrent object to control read and write access */
     private final ReadersWriter concurrentObj = new ReadersWriter();
+    /** TODO replace ReadersWriter.
+//    private final ReadWriteLock rwlock = new ReentrantReadWriteLock();
+//    private final Lock wlock = rwlock.writeLock();
+//    private final Lock rlock = rwlock.readLock();
     /** Object for synchronizing with the service expire thread */
     private final Object serviceNotifier = new Object();
     /** Object for synchronizing with the event expire thread */
@@ -314,66 +328,67 @@ class RegistrarImpl implements Registrar
     private final Object snapshotNotifier = new Object();
 
     /** Canonical ServiceType for java.lang.Object */
-    private ServiceType objectServiceType;
+    private volatile ServiceType objectServiceType;
 
     /** Log for recovering/storing state, or null if running as transient */
-    private ReliableLog log;
+    private volatile ReliableLog log;
     /** Flag indicating whether system is in a state of recovery */
-    private boolean inRecovery;
+    private volatile boolean inRecovery;
     /** Flag indicating whether system state was recovered from a snapshot */
-    private boolean recoveredSnapshot = false;
+    private volatile boolean recoveredSnapshot = false;
     /** Current number of records in the Log File since the last snapshot */
-    private int logFileSize = 0;
+    private volatile int logFileSize = 0;
 
     /** Log file must contain this many records before snapshot allowed */
-    private int persistenceSnapshotThreshold = 200;
+    private volatile int persistenceSnapshotThreshold = 200;
     /** Weight factor applied to snapshotSize when deciding to take snapshot */
-    private float persistenceSnapshotWeight = 10;
+    private volatile float persistenceSnapshotWeight = 10;
     /** Minimum value for maxServiceLease. */
-    private long minMaxServiceLease = 1000 * 60 * 5;
+    private volatile long minMaxServiceLease = 1000 * 60 * 5;
     /** Minimum value for maxEventLease. */
-    private long minMaxEventLease = 1000 * 60 * 30;
+    private volatile long minMaxEventLease = 1000 * 60 * 30;
     /** Minimum average time between lease renewals, in milliseconds. */
-    private long minRenewalInterval = 100;
+    private volatile long minRenewalInterval = 100;
     /** Port for unicast discovery */
-    private int unicastPort = 0;
+    private volatile int unicastPort = 0;
     /** The groups we are a member of */
     private volatile String[] memberGroups = { "" };
     /** The groups we should join */
-    private String[] lookupGroups = DiscoveryGroupManagement.NO_GROUPS;
+    private volatile String[] lookupGroups = DiscoveryGroupManagement.NO_GROUPS;
     /** The locators of other lookups we should join */
-    private LookupLocator[] lookupLocators = {};
+    private volatile LookupLocator[] lookupLocators = {};
     /** The attributes to use when joining (including with myself) */
-    private Entry[] lookupAttrs;
+    private volatile Entry[] lookupAttrs;
     /** Interval to wait in between sending multicast announcements */
-    private long multicastAnnouncementInterval = 1000 * 60 * 2;
+    private volatile long multicastAnnouncementInterval = 1000 * 60 * 2;
     /** Multicast announcement sequence number */
     private volatile long announcementSeqNo = 0L;
 
     /** Network interfaces to use for multicast discovery */
-    private NetworkInterface[] multicastInterfaces;
+    /** shared among threads, but not mutated after construction */
+    private volatile NetworkInterface[] multicastInterfaces;
     /** Flag indicating whether network interfaces were explicitly specified */
-    private boolean multicastInterfacesSpecified;
+    private volatile boolean multicastInterfacesSpecified;
     /** Interval to wait in between retrying failed interfaces */
-    private int multicastInterfaceRetryInterval = 1000 * 60 * 5;
+    private volatile int multicastInterfaceRetryInterval = 1000 * 60 * 5;
     /** Utility for participating in version 2 of discovery protocols */
-    private Discovery protocol2;
+    private volatile Discovery protocol2;
     /** Cached raw constraints associated with unicastDiscovery method*/
-    private InvocationConstraints rawUnicastDiscoveryConstraints;
+    private volatile InvocationConstraints rawUnicastDiscoveryConstraints;
     /** Constraints specified for incoming multicast requests */
-    private DiscoveryConstraints multicastRequestConstraints;
+    private volatile DiscoveryConstraints multicastRequestConstraints;
     /** Constraints specified for outgoing multicast announcements */
-    private DiscoveryConstraints multicastAnnouncementConstraints;
+    private volatile DiscoveryConstraints multicastAnnouncementConstraints;
     /** Constraints specified for handling unicast discovery */
-    private DiscoveryConstraints unicastDiscoveryConstraints;
+    private volatile DiscoveryConstraints unicastDiscoveryConstraints;
     /** Client subject checker to apply to incoming multicast requests */
-    private ClientSubjectChecker multicastRequestSubjectChecker;
+    private volatile ClientSubjectChecker multicastRequestSubjectChecker;
     /** Maximum time to wait for calls to finish before forcing unexport */
     private volatile long unexportTimeout = 1000 * 60 * 2;
     /** Time to wait between unexport attempts */
     private volatile long unexportWait = 1000;
     /** Client subject checker to apply to unicast discovery attempts */
-    private ClientSubjectChecker unicastDiscoverySubjectChecker;
+    private volatile ClientSubjectChecker unicastDiscoverySubjectChecker;
 
     /** Lock protecting startup and shutdown */
     private final ReadyState ready = new ReadyState();
@@ -397,6 +412,16 @@ class RegistrarImpl implements Registrar
 		configArgs, getClass().getClassLoader());
 
             loginAndRun(config,activationID,persistent,lifeCycle);
+            serviceExpirer = new ServiceExpireThread();
+            eventExpirer = new EventExpireThread();
+            multicaster = new MulticastThread();
+            announcer = new AnnounceThread();
+            snapshotter = new SnapshotThread();
+            serviceExpirer.start();
+            eventExpirer.start();
+            multicaster.start();
+            announcer.start();
+            snapshotter.start();
 	} catch (Throwable t) {
 	    logger.log(Level.SEVERE, "Reggie initialization failed", t);
 	    if (t instanceof Exception) {
@@ -423,6 +448,16 @@ class RegistrarImpl implements Registrar
     {
 	try {
             loginAndRun(config,activationID,persistent,lifeCycle);
+            serviceExpirer = new ServiceExpireThread();
+            eventExpirer = new EventExpireThread();
+            multicaster = new MulticastThread();
+            announcer = new AnnounceThread();
+            snapshotter = new SnapshotThread();
+            serviceExpirer.start();
+            eventExpirer.start();
+            multicaster.start();
+            announcer.start();
+            snapshotter.start();
 	} catch (Throwable t) {
 	    logger.log(Level.SEVERE, "Reggie initialization failed", t);
 	    if (t instanceof Exception) {
@@ -707,7 +742,7 @@ class RegistrarImpl implements Registrar
 	 */
 	public void apply(RegistrarImpl regImpl) {
 	    SvcReg oldReg =
-		(SvcReg)regImpl.serviceByID.get(reg.item.serviceID);
+                (SvcReg)regImpl.serviceByID.get(reg.item.serviceID);
 	    if (oldReg != null)
 		regImpl.deleteService(oldReg, 0);
 	    regImpl.addService(reg);
@@ -1239,7 +1274,7 @@ class RegistrarImpl implements Registrar
 	 *
 	 * @serial
 	 */
-	private int newPort;
+	private final int newPort;
 
 	/** Simple constructor */
 	public UnicastPortSetLogObj(int newPort) {
@@ -1272,7 +1307,7 @@ class RegistrarImpl implements Registrar
 	 *
 	 * @serial
 	 */
-	private String[] groups;
+	private final String[] groups;
 
 	/** Simple constructor */
 	public LookupGroupsChangedLogObj(String[] groups) {
@@ -1362,7 +1397,7 @@ class RegistrarImpl implements Registrar
 	 *
 	 * @serial
 	 */
-	private String[] groups;
+	private final String[] groups;
 
 	/** Simple constructor */
 	public MemberGroupsChangedLogObj(String[] groups) {
@@ -1558,7 +1593,10 @@ class RegistrarImpl implements Registrar
 	}
     }
 
-    /** Base class for iterating over all Items that match a Template. */
+    /** Base class for iterating over all Items that match a Template. 
+     * ItemIter are for single threaded use, however they access collections
+     * that may be accessed by other threads */
+    
     private abstract class ItemIter {
 	/** Current time */
 	public final long now = System.currentTimeMillis();
@@ -1604,7 +1642,7 @@ class RegistrarImpl implements Registrar
     /** Iterate over all Items. */
     private class AllItemIter extends ItemIter {
 	/** Iterator over serviceByID */
-	private final Iterator iter;
+	private final Iterator<SvcReg> iter;
 
 	/** Assumes the empty template */
 	public AllItemIter() {
@@ -1614,12 +1652,14 @@ class RegistrarImpl implements Registrar
 	}
 
 	/** Set reg to the next matching element, or null if none */
-	protected void step() {
-	    while (iter.hasNext()) {
-		reg = (SvcReg)iter.next();
-		if (reg.leaseExpiration > now)
-		    return;
-	    }
+	protected final void step() {
+            synchronized (serviceByID){
+                while (iter.hasNext()) {
+                    reg = iter.next();
+                    if (reg.leaseExpiration > now)
+                        return;
+                }
+            }
 	    reg = null;
 	}
     }
@@ -1627,49 +1667,65 @@ class RegistrarImpl implements Registrar
     /** Iterates over all services that match template's service types */
     private class SvcIterator extends ItemIter {
 	/** Iterator for list of matching services. */
-        private final Iterator services;
+        private final Iterator<SvcReg> services;
+        private final Map<ServiceID,SvcReg> mutex;
 	
 	/**
 	 * tmpl.serviceID == null and
 	 * tmpl.serviceTypes is not empty
 	 */
+        @SuppressWarnings("unchecked")
         public SvcIterator(Template tmpl) {
 	    super(tmpl);
-	    Map map = (Map) serviceByTypeName.get(
+	    Map<ServiceID,SvcReg> map = serviceByTypeName.get(
 	       tmpl.serviceTypes[0].getName());
-	    services = map != null ? map.values().iterator() :
-		Collections.EMPTY_LIST.iterator();
+            mutex = (Map<ServiceID, SvcReg>) (map != null ? map : Collections.emptyMap());
+	    services = mutex.values().iterator();
 	    step();
 	}
 	
         /** Set reg to the next matching element, or null if none. */
-        protected void step() {
+        protected final void step() {
 	    if (tmpl.serviceTypes.length > 1) {
-		while (services.hasNext()) {
-		    reg = (SvcReg) services.next();
-		    if (reg.leaseExpiration > now &&
-			matchType(tmpl.serviceTypes, reg.item.serviceType) &&
-			matchAttributes(tmpl, reg.item))
-			return;
-		}		
+                synchronized (mutex){
+                    while (services.hasNext()) {
+                        reg = services.next();
+                        if (reg.leaseExpiration > now &&
+                            matchType(tmpl.serviceTypes, reg.item.serviceType) &&
+                            matchAttributes(tmpl, reg.item))
+                            return;
+                    }
+                }
 	    } else {
-		while (services.hasNext()) {
-		    reg = (SvcReg) services.next();
-		    if (reg.leaseExpiration > now &&
-			matchAttributes(tmpl, reg.item))
-			return;
-		}
+                synchronized (mutex){
+                    while (services.hasNext()) {
+                        reg = (SvcReg) services.next();
+                        if (reg.leaseExpiration > now &&
+                            matchAttributes(tmpl, reg.item))
+                            return;
+                    }
+                }
 	    }
 	    reg = null;
 	}
     }
-
     /** Iterate over all matching Items by attribute value. */
     private class AttrItemIter extends ItemIter {
 	/** SvcRegs obtained from serviceByAttr for chosen attr */
-	protected ArrayList svcs;
+	protected final List<SvcReg> svcs;
 	/** Current index into svcs */
-	protected int svcidx;
+	protected int svcidx = 0;
+        
+        protected AttrItemIter(Template tmpl, List<SvcReg> svcs){
+            super(tmpl);
+            if (svcs != null) {
+		svcidx = svcs.size();
+                this.svcs = svcs;
+		step();
+	    } else {
+                this.svcs = Collections.emptyList();
+            }
+        }
 
 	/**
 	 * tmpl.serviceID == null and
@@ -1679,27 +1735,33 @@ class RegistrarImpl implements Registrar
 	public AttrItemIter(Template tmpl, int setidx, int fldidx) {
 	    super(tmpl);
 	    EntryRep set = tmpl.attributeSetTemplates[setidx];
-	    HashMap[] attrMaps =
-		(HashMap[])serviceByAttr.get(getDefiningClass(set.eclass,
+	    Map<Object,List<SvcReg>>[] attrMaps =
+		serviceByAttr.get(getDefiningClass(set.eclass,
 							      fldidx));
+            List<SvcReg> svcs = null;
 	    if (attrMaps != null && attrMaps[fldidx] != null) {
-		svcs = (ArrayList)attrMaps[fldidx].get(set.fields[fldidx]);
+		svcs = attrMaps[fldidx].get(set.fields[fldidx]);
 		if (svcs != null) {
 		    svcidx = svcs.size();
+                    this.svcs = svcs;
 		    step();
-		}
-	    }
+                } else {
+                    this.svcs = Collections.emptyList();
+                }
+	    } else {
+                this.svcs = Collections.emptyList();
+            }
 	}
 
 	/** Simple constructor */
 	protected AttrItemIter(Template tmpl) {
-	    super(tmpl);
+	    this(tmpl, null);
 	}
 
 	/** Set reg to the next matching element, or null if none. */
-	protected void step() {
+	protected final void step() {
 	    while (--svcidx >= 0) {
-		reg = (SvcReg)svcs.get(svcidx);
+		reg = svcs.get(svcidx);
 		if (reg.leaseExpiration > now &&
 		    matchAttributes(tmpl, reg.item))
 		    return;
@@ -1717,8 +1779,7 @@ class RegistrarImpl implements Registrar
 	 * eclass has no fields
 	 */
 	public EmptyAttrItemIter(Template tmpl, EntryClass eclass) {
-	    super(tmpl);
-	    svcs = (ArrayList)serviceByEmptyAttr.get(eclass);
+	    super(tmpl,serviceByEmptyAttr.get(eclass) );
 	    if (svcs != null) {
 		svcidx = svcs.size();
 		step();
@@ -1733,9 +1794,10 @@ class RegistrarImpl implements Registrar
 	/** Current index into entryClasses */
 	private int classidx;
 	/** Values iterator for current HashMap */
-	private Iterator iter;
+	private Iterator<List<SvcReg>> iter;
+        private Object mutex;
 	/** SvcRegs obtained from iter or serviceByEmptyAttr */
-	private ArrayList svcs;
+	private List<SvcReg> svcs;
 	/** Current index into svcs */
 	private int svcidx = 0;
 
@@ -1749,14 +1811,15 @@ class RegistrarImpl implements Registrar
 	    dupsPossible = true;
 	    eclass = tmpl.attributeSetTemplates[0].eclass;
 	    classidx = entryClasses.size();
+            mutex = new Object();
 	    step();
 	}
 
 	/** Set reg to the next matching element, or null if none */
-	protected void step() {
+	protected final void step() {
 	    do {
 		while (--svcidx >= 0) {
-		    reg = (SvcReg)svcs.get(svcidx);
+		    reg = svcs.get(svcidx);
 		    if (reg.leaseExpiration > now &&
 			matchAttributes(tmpl, reg.item))
 			return;
@@ -1771,11 +1834,13 @@ class RegistrarImpl implements Registrar
 	 */
 	private boolean stepValue() {
 	    while (true) {
-		if (iter != null && iter.hasNext()) {
-		    svcs = (ArrayList)iter.next();
-		    svcidx = svcs.size();
-		    return true;
-		}
+                synchronized (mutex){ //REMIND: Locking not satisfactory during iteration.
+                    if (iter != null && iter.hasNext()) {
+                        svcs = iter.next();
+                        svcidx = svcs.size();
+                        return true;
+                    }
+                }
 		if (!stepClass())
 		    return false;
 		if (iter == null)
@@ -1791,16 +1856,19 @@ class RegistrarImpl implements Registrar
 	 */
 	private boolean stepClass() {
 	    while (--classidx >= 0) {
-		EntryClass cand = (EntryClass)entryClasses.get(classidx);
+		EntryClass cand = entryClasses.get(classidx);
 		if (!eclass.isAssignableFrom(cand))
 		    continue;
 		if (cand.getNumFields() > 0) {
 		    cand = getDefiningClass(cand, cand.getNumFields() - 1);
-		    HashMap[] attrMaps = (HashMap[])serviceByAttr.get(cand);
-		    iter = attrMaps[attrMaps.length - 1].values().iterator();
+		    Map<Object,List<SvcReg>>[] attrMaps = serviceByAttr.get(cand);
+                    Map<Object,List<SvcReg>> mutex = attrMaps[attrMaps.length - 1];
+                    this.mutex = mutex;
+		    iter = mutex.values().iterator();
 		} else {
 		    iter = null;
-		    svcs = (ArrayList)serviceByEmptyAttr.get(cand);
+                    mutex = new Object();
+		    svcs = serviceByEmptyAttr.get(cand);
 		    svcidx = svcs.size();
 		}
 		return true;
@@ -1815,7 +1883,7 @@ class RegistrarImpl implements Registrar
 	/** tmpl.serviceID != null */
 	public IDItemIter(Template tmpl) {
 	    super(tmpl);
-	    reg = (SvcReg)serviceByID.get(tmpl.serviceID);
+	    reg = serviceByID.get(tmpl.serviceID);
 	    if (reg != null &&
 		(reg.leaseExpiration <= now || !matchItem(tmpl, reg.item)))
 		reg = null;
@@ -2207,7 +2275,7 @@ class RegistrarImpl implements Registrar
 		    long now = System.currentTimeMillis();
 		    minEventExpiration = Long.MAX_VALUE;
 		    while (!eventByTime.isEmpty()) {
-			EventReg reg = (EventReg)eventByTime.firstKey();
+			EventReg reg = (EventReg) eventByTime.firstKey();
 			if (reg.leaseExpiration > now) {
 			    minEventExpiration = reg.leaseExpiration;
 			    break;
@@ -3651,9 +3719,9 @@ class RegistrarImpl implements Registrar
 
     /** Adds a service registration to types in its hierarchy */
     private void addServiceByTypes(ServiceType type, SvcReg reg) {
-	Map map = (Map) serviceByTypeName.get(type.getName());
+	Map<ServiceID,SvcReg> map = serviceByTypeName.get(type.getName());
 	if (map == null) {
-	    map = new HashMap();
+	    map = Collections.synchronizedMap(new HashMap<ServiceID,SvcReg>());
 	    serviceByTypeName.put(type.getName(), map);
 	}
 	map.put(reg.item.serviceID, reg);	
@@ -3669,7 +3737,7 @@ class RegistrarImpl implements Registrar
     /** Deletes a service registration from types in its hierarchy */
     private void deleteServiceFromTypes(ServiceType type, SvcReg reg)
     {
-	Map map = (Map) serviceByTypeName.get(type.getName());
+	Map<ServiceID,SvcReg> map = serviceByTypeName.get(type.getName());
 	if (map != null) {
 	    map.remove(reg.item.serviceID);
 	    if ((map.isEmpty()) && !type.equals(objectServiceType))
@@ -4115,14 +4183,16 @@ class RegistrarImpl implements Registrar
 	    }
 	    return;
 	}
-	ArrayList regs = (ArrayList)serviceByEmptyAttr.get(eclass);
-	if (regs == null) {
-	    regs = new ArrayList(2);
-	    regs.add(reg);
-	    serviceByEmptyAttr.put(eclass, regs);
-	} else if (!regs.contains(reg)) {
-	    regs.add(reg);
-	}
+        synchronized (serviceByEmptyAttr){
+            List<SvcReg> regs = serviceByEmptyAttr.get(eclass);
+            if (regs == null) {
+                regs = Collections.synchronizedList(new ArrayList<SvcReg>(2));
+                regs.add(reg);
+                serviceByEmptyAttr.put(eclass, regs);
+            } else if (!regs.contains(reg)) {
+                regs.add(reg);
+            }
+        }
     }
 
     /**
@@ -4139,42 +4209,46 @@ class RegistrarImpl implements Registrar
 	deleteInstance(eclass);
 	Object[] fields = entry.fields;
 	if (fields.length == 0) {
-	    ArrayList regs = (ArrayList)serviceByEmptyAttr.get(eclass);
-	    if (regs == null || (checkDups && hasEmptyAttr(reg, eclass)))
-		return;
-	    int idx = regs.indexOf(reg);
-	    if (idx >= 0) {
-		regs.remove(idx);
-		if (regs.isEmpty())
-		    serviceByEmptyAttr.remove(eclass);
-	    }
-	    return;
+            List<SvcReg> regs = serviceByEmptyAttr.get(eclass);
+            if (regs == null || (checkDups && hasEmptyAttr(reg, eclass)))
+                return;
+            int idx = regs.indexOf(reg);
+            if (idx >= 0) {
+                synchronized (serviceByEmptyAttr){
+                    regs.remove(idx);
+                    if (regs.isEmpty())
+                        serviceByEmptyAttr.remove(eclass);
+                }
+            }
+            return;
 	}
 	/* walk backwards to make getDefiningClass more efficient */
 	for (int fldidx = fields.length; --fldidx >= 0; ) {
 	    eclass = getDefiningClass(eclass, fldidx);
-	    HashMap[] attrMaps = (HashMap[])serviceByAttr.get(eclass);
-	    if (attrMaps == null ||
-		attrMaps[fldidx] == null ||
-		(checkDups && hasAttr(reg, eclass, fldidx, fields[fldidx])))
-		continue;
-	    HashMap map = attrMaps[fldidx];
-	    Object value = fields[fldidx];
-	    ArrayList regs = (ArrayList)map.get(value);
-	    if (regs == null)
-		continue;
-	    int idx = regs.indexOf(reg);
-	    if (idx < 0)
-		continue;
-	    regs.remove(idx);
-	    if (!regs.isEmpty())
-		continue;
-	    map.remove(value);
-	    if (!map.isEmpty())
-		continue;
-	    attrMaps[fldidx] = null;
-	    if (allNull(attrMaps))
-		serviceByAttr.remove(eclass);
+            synchronized (serviceByAttr){
+                Map<Object,List<SvcReg>>[] attrMaps = serviceByAttr.get(eclass);
+                if (attrMaps == null ||
+                    attrMaps[fldidx] == null ||
+                    (checkDups && hasAttr(reg, eclass, fldidx, fields[fldidx])))
+                    continue;
+                Map<Object,List<SvcReg>> map = attrMaps[fldidx];
+                Object value = fields[fldidx];
+                List<SvcReg> regs = map.get(value);
+                if (regs == null)
+                    continue;
+                int idx = regs.indexOf(reg);
+                if (idx < 0)
+                    continue;
+                regs.remove(idx);
+                if (!regs.isEmpty())
+                    continue;
+                map.remove(value);
+                if (!map.isEmpty())
+                    continue;
+                attrMaps[fldidx] = null;
+                if (allNull(attrMaps))
+                    serviceByAttr.remove(eclass);
+            }
 	}
     }
 
@@ -4191,14 +4265,16 @@ class RegistrarImpl implements Registrar
 	    Object nval = values[fldidx];
 	    if (nval != null && !nval.equals(oval)) {
 		eclass = getDefiningClass(eclass, fldidx);
-		HashMap map = addAttr(reg, eclass, fldidx, nval);
+		Map<Object,List<SvcReg>> map = addAttr(reg, eclass, fldidx, nval);
 		entry.fields[fldidx] = nval;
 		if (hasAttr(reg, eclass, fldidx, oval))
 		    continue;
-		ArrayList regs = (ArrayList)map.get(oval);
-		regs.remove(regs.indexOf(reg));
-		if (regs.isEmpty())
-		    map.remove(oval); /* map cannot become empty */
+                synchronized (serviceByAttr){
+                    List<SvcReg> regs = map.get(oval);
+                    regs.remove(regs.indexOf(reg));
+                    if (regs.isEmpty())
+                        map.remove(oval); /* map cannot become empty */
+                }
 	    }
 	}
     }
@@ -4208,29 +4284,32 @@ class RegistrarImpl implements Registrar
      * defining class and field, if it isn't already there.  Return
      * the HashMap for the given class and field.
      */
-    private HashMap addAttr(SvcReg reg,
+    @SuppressWarnings("unchecked")
+    private Map<Object,List<SvcReg>> addAttr(SvcReg reg,
 			    EntryClass eclass,
 			    int fldidx,
 			    Object value)
     {
-	HashMap[] attrMaps = (HashMap[])serviceByAttr.get(eclass);
-	if (attrMaps == null) {
-	    attrMaps = new HashMap[eclass.getNumFields()];
-	    serviceByAttr.put(eclass, attrMaps);
-	}
-	HashMap map = attrMaps[fldidx];
-	if (map == null) {
-	    map = new HashMap(11);
-	    attrMaps[fldidx] = map;
-	}
-	ArrayList regs = (ArrayList)map.get(value);
-	if (regs == null) {
-	    regs = new ArrayList(3);
-	    map.put(value, regs);
-	} else if (regs.contains(reg))
-	    return map;
-	regs.add(reg);
-	return map;
+        synchronized (serviceByAttr){
+            Map<Object,List<SvcReg>>[] attrMaps = serviceByAttr.get(eclass);
+            if (attrMaps == null) {
+                attrMaps = new Map[eclass.getNumFields()];
+                serviceByAttr.put(eclass, attrMaps);
+            }
+            Map<Object,List<SvcReg>> map = attrMaps[fldidx];
+            if (map == null) {
+                map = Collections.synchronizedMap(new HashMap<Object,List<SvcReg>>(11));
+                attrMaps[fldidx] = map;
+            }
+            List<SvcReg> regs = map.get(value);
+            if (regs == null) {
+                regs = Collections.synchronizedList(new ArrayList<SvcReg>(3));
+                map.put(value, regs);
+            } else if (regs.contains(reg))
+                return map;
+            regs.add(reg);
+            return map;
+        }
     }
 
     /**
@@ -4243,7 +4322,7 @@ class RegistrarImpl implements Registrar
 	    entryClasses.add(eclass);
 	    idx = entryClasses.size() - 1;
 	}
-	eclass = (EntryClass) entryClasses.get(idx);
+	eclass = entryClasses.get(idx);
 	eclass.setNumInstances(eclass.getNumInstances() + 1);	
     }
 
@@ -4294,7 +4373,7 @@ class RegistrarImpl implements Registrar
     private EntryClass getEmptyEntryClass(EntryClass eclass) {
 	EntryClass match = null;
 	for (int i = entryClasses.size(); --i >= 0; ) {
-	    EntryClass cand = (EntryClass)entryClasses.get(i);
+	    EntryClass cand = entryClasses.get(i);
 	    if (eclass.isAssignableFrom(cand)) {
 		if (cand.getNumFields() != 0 || match != null)
 		    return null;
@@ -4305,18 +4384,18 @@ class RegistrarImpl implements Registrar
     }
 
     /** Returns a list of services that match all types passed in */
-    private ArrayList matchingServices(ServiceType[] types) {
-	ArrayList matches = new ArrayList();
+    private List<SvcReg> matchingServices(ServiceType[] types) {
+	List<SvcReg> matches = new ArrayList<SvcReg>();
 	if (isEmpty(types)) {
-	    Map map = (Map) serviceByTypeName.get(objectServiceType.getName());
+	    Map<ServiceID,SvcReg> map = serviceByTypeName.get(objectServiceType.getName());
 	    matches.addAll(map.values());
 	} else {
-	    Map map = (Map) serviceByTypeName.get(types[0].getName());
+	    Map<ServiceID,SvcReg> map = serviceByTypeName.get(types[0].getName());
 	    if (map != null)
 	        matches.addAll(map.values());
 	    if (types.length > 1) {
-	        for (Iterator it = matches.iterator(); it.hasNext(); ) {
-		    SvcReg reg = (SvcReg) it.next();
+	        for (Iterator<SvcReg> it = matches.iterator(); it.hasNext(); ) {
+		    SvcReg reg = it.next();
 		    if (!matchType(types, reg.item.serviceType))
 		        it.remove();
 	        }
@@ -4331,28 +4410,30 @@ class RegistrarImpl implements Registrar
     {
 	if (eclass.getNumFields() == 0)
 	    return pickCodebase(eclass,
-				(ArrayList)serviceByEmptyAttr.get(eclass),
+				serviceByEmptyAttr.get(eclass),
 				now);
 	int fldidx = eclass.getNumFields() - 1;
-	HashMap[] attrMaps =
-	    (HashMap[])serviceByAttr.get(getDefiningClass(eclass, fldidx));
-	for (Iterator iter = attrMaps[fldidx].values().iterator();
-	     iter.hasNext(); )
-	{
-	    try {
-		return pickCodebase(eclass, (ArrayList)iter.next(), now);
-	    } catch (ClassNotFoundException e) {
-	    }
-	}
-	throw new ClassNotFoundException();
+	Map<Object,List<SvcReg>>[] attrMaps =
+	    serviceByAttr.get(getDefiningClass(eclass, fldidx));
+        synchronized (attrMaps[fldidx]){
+            for (Iterator<List<SvcReg>> iter = attrMaps[fldidx].values().iterator();
+                 iter.hasNext(); )
+            {
+                try {
+                    return pickCodebase(eclass, iter.next(), now);
+                } catch (ClassNotFoundException e) {
+                }
+            }
+            throw new ClassNotFoundException();
+        }
     }
 
     /** Return any valid codebase for an entry of the exact given class. */
-    private String pickCodebase(EntryClass eclass, ArrayList svcs, long now)
+    private String pickCodebase(EntryClass eclass, List<SvcReg> svcs, long now)
 	throws ClassNotFoundException
     {
 	for (int i = svcs.size(); --i >= 0; ) {
-	    SvcReg reg = (SvcReg)svcs.get(i);
+	    SvcReg reg = svcs.get(i);
 	    if (reg.leaseExpiration <= now)
 		continue;
 	    EntryRep[] sets = reg.item.attributeSets;
@@ -4684,12 +4765,7 @@ class RegistrarImpl implements Registrar
 		DiscoveryConstraints.multicastAnnouncementMethod));
 	unicastDiscoveryConstraints = DiscoveryConstraints.process(
 	    rawUnicastDiscoveryConstraints);
-	serviceExpirer = new ServiceExpireThread();
-	eventExpirer = new EventExpireThread();
 	unicaster = new UnicastThread(unicastPort);
-	multicaster = new MulticastThread();
-	announcer = new AnnounceThread();
-	snapshotter = new SnapshotThread();
 	if (myServiceID == null) {
 	    myServiceID = newServiceID();
 	}
@@ -4733,11 +4809,7 @@ class RegistrarImpl implements Registrar
 				 discoer, null, config);
 
 	/* start up all the daemon threads */
-	serviceExpirer.start();
-	eventExpirer.start();
 	unicaster.start();
-	multicaster.start();
-	announcer.start();
         
         /* Shutdown hook so reggie sends a final announcement
          * packet if VM is terminated.  If reggie is terminated
@@ -4758,7 +4830,6 @@ class RegistrarImpl implements Registrar
 	    }
 	}));
         
-        snapshotter.start();
 	if (logger.isLoggable(Level.INFO)) {
 	    logger.log(Level.INFO, "started Reggie: {0}, {1}, {2}",
 		       new Object[]{ myServiceID,
@@ -4768,7 +4839,8 @@ class RegistrarImpl implements Registrar
 	ready.ready();
     }
 
-    /** The code that does the real work of register. */
+    /** The code that does the real work of register.
+     * called while holding concurrentObj.writeLock() */
     private ServiceRegistration registerDo(Item nitem, long leaseDuration)
     {
 	if (nitem.service == null)
@@ -4783,16 +4855,18 @@ class RegistrarImpl implements Registrar
 	long now = System.currentTimeMillis();
 	if (nitem.serviceID == null) {
 	    /* new service, match on service object */
-	    Map svcs = (Map)serviceByTypeName.get(nitem.serviceType.getName());
+	    Map<ServiceID,SvcReg> svcs = serviceByTypeName.get(nitem.serviceType.getName());
 	    if (svcs != null) {
-		for (Iterator it = svcs.values().iterator(); it.hasNext(); ) {
-		    SvcReg reg = (SvcReg)it.next();
-		    if (nitem.service.equals(reg.item.service)) {
-			nitem.serviceID = reg.item.serviceID;
-			deleteService(reg, now);
-			break;
-		    }
-		}
+                synchronized (svcs){
+                    for (Iterator<SvcReg> it = svcs.values().iterator(); it.hasNext(); ) {
+                        SvcReg reg = it.next();
+                        if (nitem.service.equals(reg.item.service)) {
+                            nitem.serviceID = reg.item.serviceID;
+                            deleteService(reg, now);
+                            break;
+                        }
+                    }
+                }
 	    }
 	    if (nitem.serviceID == null)
 		nitem.serviceID = newServiceID();
@@ -5001,7 +5075,7 @@ class RegistrarImpl implements Registrar
      */
     private Object[] getFieldValuesDo(Template tmpl, int setidx, int fldidx)
     {
-	ArrayList values = new ArrayList();
+	List<Object> values = new ArrayList<Object>();
 	EntryRep etmpl = tmpl.attributeSetTemplates[setidx];
 	if (tmpl.serviceID == null &&
 	    isEmpty(tmpl.serviceTypes) &&
@@ -5011,24 +5085,26 @@ class RegistrarImpl implements Registrar
 	    long now = System.currentTimeMillis();
 	    EntryClass eclass = getDefiningClass(etmpl.eclass, fldidx);
 	    boolean checkAttr = !eclass.equals(etmpl.eclass);
-	    HashMap[] attrMaps = (HashMap[])serviceByAttr.get(eclass);
+	    Map<Object,List<SvcReg>>[] attrMaps = serviceByAttr.get(eclass);
 	    if (attrMaps != null && attrMaps[fldidx] != null) {
-		for (Iterator iter = attrMaps[fldidx].entrySet().iterator();
-		     iter.hasNext(); )
-		{
-		    Map.Entry ent = (Map.Entry)iter.next();
-		    ArrayList regs = (ArrayList)ent.getValue();
-		    Object value = ent.getKey();
-		    for (int i = regs.size(); --i >= 0; ) {
-			SvcReg reg = (SvcReg)regs.get(i);
-			if (reg.leaseExpiration > now &&
-			    (!checkAttr ||
-			     hasAttr(reg, etmpl.eclass, fldidx, value))) {
-			    values.add(value);
-			    break;
-			}
-		    }
-		}
+                synchronized (attrMaps[fldidx]){
+                    for (Iterator<Map.Entry<Object,List<SvcReg>>> iter = attrMaps[fldidx].entrySet().iterator();
+                         iter.hasNext(); )
+                    {
+                        Map.Entry<Object,List<SvcReg>> ent = iter.next();
+                        List<SvcReg> regs = ent.getValue();
+                        Object value = ent.getKey();
+                        for (int i = regs.size(); --i >= 0; ) {
+                            SvcReg reg = regs.get(i);
+                            if (reg.leaseExpiration > now &&
+                                (!checkAttr ||
+                                 hasAttr(reg, etmpl.eclass, fldidx, value))) {
+                                values.add(value);
+                                break;
+                            }
+                        }
+                    }
+                }
 	    }
 	} else {
 	    for (ItemIter iter = matchingItems(tmpl); iter.hasNext(); ) {
@@ -5582,13 +5658,15 @@ class RegistrarImpl implements Registrar
 	stream.writeLong(announcementSeqNo);
 	marshalAttributes(lookupAttrs, stream);
 	marshalLocators(lookupLocators, stream);
-	for (Iterator iter = serviceByID.entrySet().iterator(); 
-	     iter.hasNext(); )
-	{
-	    Map.Entry entry = (Map.Entry) iter.next();
-	    if (myServiceID != entry.getKey())
-		stream.writeObject(entry.getValue());
-	}
+        synchronized (serviceByID){
+            for (Iterator iter = serviceByID.entrySet().iterator(); 
+                 iter.hasNext(); )
+            {
+                Map.Entry entry = (Map.Entry) iter.next();
+                if (myServiceID != entry.getKey())
+                    stream.writeObject(entry.getValue());
+            }
+        }
 	stream.writeObject(null);
 	for (Iterator iter = eventByID.values().iterator(); iter.hasNext(); )
 	{