river-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From peter_firmst...@apache.org
Subject svn commit: r1634322 [33/41] - in /river/jtsk/skunk/qa_refactor/trunk: qa/src/com/sun/jini/qa/harness/ qa/src/com/sun/jini/test/impl/end2end/e2etest/ qa/src/com/sun/jini/test/impl/joinmanager/ qa/src/com/sun/jini/test/impl/mahalo/ qa/src/com/sun/jini/t...
Date Sun, 26 Oct 2014 13:17:31 GMT
Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/event/EventType.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/event/EventType.java?rev=1634322&r1=1634321&r2=1634322&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/event/EventType.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/event/EventType.java Sun Oct
26 13:17:28 2014
@@ -1,496 +1,496 @@
-/*
- * 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.norm.event;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.rmi.MarshalledObject;
-import java.rmi.RemoteException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import net.jini.core.event.RemoteEvent;
-import net.jini.core.event.RemoteEventListener;
-import net.jini.core.event.UnknownEventException;
-import net.jini.security.ProxyPreparer;
-
-import com.sun.jini.constants.ThrowableConstants;
-import com.sun.jini.logging.Levels;
-import com.sun.jini.thread.RetryTask;
-import com.sun.jini.thread.WakeupManager;
-import java.util.concurrent.ExecutorService;
-import net.jini.io.MarshalledInstance;
-
-/**
- * Representation of an event type the supports a single registrant.
- * The registrant, event ID, and event sequence number information
- * portions of this object are preserved when serialized.  The send
- * monitor, and currently scheduled event sends are not.
- *
- * @author Sun Microsystems, Inc.
- */
-// $$$ I am not sure if this class does too much locking, or too little.
-// It does too little in that it does not do any locking during serialization
-// It does too much in that Norm's current locking discipline means that for
-// the most part this class does not have to worry about multiple threads
-// of control entering at one time.
-// Before we make this a general utility we have to re-think the locking
-// strategy.
-public class EventType implements Serializable {
-    private static final long serialVersionUID = 2;
-
-    /** Logger for logging messages for this class */
-    private static final Logger logger = Logger.getLogger("com.sun.jini.norm");
-
-    /**
-     * Listener registered for events of this type.  Stored in 
-     * marshalled form so object the <code>EventType</code> object can
-     * be recovered even if the listener's codebase is not available.
-     * If this field is <code>null</code>, <code>listener</code>
and 
-     * <code>handback</code> will be also.  
-     * @serial
-     */
-    private MarshalledObject marshalledListener;
-
-    /** Transient cache of listener in unmarshalled form */
-    private transient RemoteEventListener listener;
-
-    /**
-     * The proxy preparer to use to prepare a newly unmarshalled listener, or
-     * null if this instance was created using an already prepared listener,
-     * which is how instances are created initially.
-     */
-    private transient ProxyPreparer recoveredListenerPreparer;
-
-    /**
-     * Handback object associated with current listener.
-     * @serial
-     */
-    private MarshalledObject handback;
-
-    /** 
-     * Sequence number of the current listener/handback pair, incremented
-     * every time a new listener is set (even if the objects 
-     * are equivalent)
-     * @serial
-     */
-    private long registrationNumber;
-
-    /**
-     * Last event sequence number we used
-     * @serial
-     */
-    private long lastSeqNum;
-
-    /**
-     * Our event ID
-     * @serial
-     */
-    private final long evID;
-
-    /** 
-     * Object we check with to ensure leases have not expired and notify
-     * when we get a definite exception during an event send attempt.
-     * If this field is <code>null</code> generator will be also.
-     */
-    private transient SendMonitor monitor;
-
-    /** 
-     * Event type generator that created us. If this field is
-     * <code>null</code> monitor will be also.
-     */
-    private transient EventTypeGenerator generator;
-
-    /**
-     * Simple constructor.  Initially the last sequence number is set to 0.
-     * @param generator EventTypeGenerator that is creating this event type
-     * @param monitor Object which is to monitor the sending of events
-     *	      of this type
-     * @param evID event ID of this event type
-     * @param listener the listener events of this type should go to
-     * @param handback the object that should be passed to listener
-     *        as part of the event
-     * @throws IOException if the listener cannot be serialized 
-     */
-    EventType(EventTypeGenerator generator, SendMonitor monitor, long evID,
-	      RemoteEventListener listener, MarshalledObject handback)
-        throws IOException
-    {
-	if (generator == null) {
-	    throw new NullPointerException("EventType(): Must create event " +
-                "type objects with a non-null generator");
-	}
-
-	if (monitor == null) {
-	    throw new NullPointerException("EventType(): Must create event " +
-                "type objects with a non-null monitor");
-	}
-
-	this.generator = generator;
-	this.monitor = monitor;
-	this.evID = evID;
-	setLastSequenceNumber(0);
-	setListener(listener, handback);
-    }    
-
-    /** Utility method to null out listener */
-    private void clearListener() {
-	listener = null;
-	handback = null;
-	marshalledListener = null;
-    }
-
-    /**
-     * (Re)set the listener for this type of event.  Any pending
-     * events that have not yet been sent will be sent to the new
-     * listener, passing the new handback.  Setting the listener to
-     * <code>null</code> will cancel the sending of all pending
-     * events.  
-     *
-     * @param listener the listener events of this type should go to
-     * @param handback the object that should be passed to listener
-     *        as part of the event
-     * @throws IOException if listener cannot be serialized
-     */
-    public final synchronized void setListener(RemoteEventListener listener, 
-					 MarshalledObject    handback)
-        throws IOException
-    {
-	registrationNumber++;
-	
-	if (listener == null) {
-	    clearListener();
-	} else {	    
-	    marshalledListener = 
-                new MarshalledInstance(listener).convertToMarshalledObject();
-	    this.listener = listener;
-	    this.handback = handback;
-	}
-    }
-
-    /**
-     * Returns <code>true</code> if there is a listener registered for this 
-     * event type.
-     */
-    public synchronized boolean haveListener() {
-	return marshalledListener != null;
-    }
-
-    /**
-     * Convince method to get the listener.
-     * @return the listener, or <code>null</code> if the listener can't be
-     *	       unpacked or prepared, or there is no listener
-     * synchronized externally
-     */
-    private RemoteEventListener getListener() {
-	if (!haveListener()) 
-	    return null;
-            
-	if (listener != null) 
-	    return listener;
-
-	// There is a listener, but it is not unpacked yet, try to unpack
-	RemoteEventListener unpreparedListener = null;
-	try {
-	    unpreparedListener =
-		(RemoteEventListener) new MarshalledInstance(marshalledListener).get(false);
-	} catch (IOException e) {
-	    logger.log(Levels.HANDLED,
-		       "Problem unmarshalling listener -- will retry later",
-		       e);
-	    // $$$ is this really the right thing to do?
-	    // we probably really have a corrupted marshalledListener here
-	} catch (ClassNotFoundException e) {
-	    logger.log(Levels.HANDLED,
-		       "Problem unmarshalling listener -- will retry later",
-		       e);
-	}
-
-	if (unpreparedListener != null) {
-	    // Prepare the listener
-	    try {
-		listener = (RemoteEventListener)
-		    recoveredListenerPreparer.prepareProxy(unpreparedListener);
-	    } catch (RemoteException e) {
-		logger.log(Levels.HANDLED,
-			   "Problem preparing listener -- will retry later",
-			   e);
-	    } catch (SecurityException e) {
-		logger.log(Levels.HANDLED,
-			   "Problem preparing listener -- will retry later",
-			   e);
-	    }
-	}
-
-	return listener;
-    }
-
-    /**
-     * Atomically clear the current registration if its sequence
-     * number matches the passed in sequence number.  If the
-     * replacement occurs it will have the same effect as calling
-     * <code>setListener(null, null)</code>.
-     * <p>
-     * Can be used by code that needs to remove event registrations in
-     * response to exceptions thrown during event delivery without
-     * risking clobbering new registrations.
-     * @param oldSequenceNumber sequence number of the 
-     *        registration that had a problem 
-     * @return <code>true</code> if the state of the object was
-     * changed and <code>false</code> otherwise
-     * @see EventType#setListener 
-     */
-    public synchronized boolean clearListenerIfSequenceMatch(
-        long oldSequenceNumber) 
-    {
-	if (oldSequenceNumber == registrationNumber) {
-	    clearListener();
-	    return true;
-	}
-
-	return false;
-    }
-
-    /**
-     * Set the object's notion of the last sequence number.  The next event
-     * scheduled to be sent will have a sequence number one greater than
-     * the value past to this call.
-     * <p>
-     * @param seqNum value for the last sequence number
-     */
-    public final synchronized void setLastSequenceNumber(long seqNum) {
-	lastSeqNum = seqNum;
-    }
-
-    /**
-     * Return the sequence number of the last event that was scheduled
-     * to be sent.  Intended primarily for creating
-     * <code>EventRegistration</code> objects and the like.
-     */
-    public synchronized long getLastSequenceNumber () {
-	return lastSeqNum;
-    }
-    
-    /**
-     * Return the <code>long</code> that was uniquely associated with this
-     * object when it was created.
-     */
-    public long getEventID() {
-	return evID;
-    }
-
-    /**
-     * Schedule the sending of an event.  This event will be sent to
-     * the currently registered listener.  If the listener changes
-     * before the the event is successfully sent the event will be sent
-     * to the new listener.  If the current listener is
-     * <code>null</code> this call will have no affect aside from
-     * incrementing the sequence number.
-     * @param factory an object that will be used to create the
-     * <code>Event</code> object when necessary
-     * @return the sequence number assigned to the event
-     * @throws IllegalStateException if this method is called
-     *         after the object has be deserialized and before
-     *         <code>restoreTransientState</code> has been called
-     * @see EventType#restoreTransientState
-     */
-    public synchronized long sendEvent(EventFactory factory) {
-	if (generator == null) {
-	    // Have not had our state restored, complain
-	    throw new IllegalStateException("EventType.sendEvent:" +
-	        "called before state was fully restored");
-	}
-
-	// Even if there is no listener, an event has occurred, so
-	// increment the sequence number (note this a stronger
-	// guarantee that the Jini Distributed Event Specification,
-	// but one that is required by the LRS spec).
-	lastSeqNum++;
-
-	// If we don't have a listener we don't need do anything else
-	if (!haveListener())
-	    return lastSeqNum;
-	
-	final ExecutorService mgr = generator.getTaskManager();
-	final WakeupManager wMgr = generator.getWakeupManager();
-	mgr.execute(new SendTask(mgr, wMgr, factory, lastSeqNum));
-	
-	return lastSeqNum;
-    }
-
-    /**
-     * Increment the sequence number and return the result. This
-     * method is useful if an event occurs that needs to be noted
-     * but from some reason it is impossible to deliver the event.
-     *
-     * @return the new value for the sequence number
-     */
-    public synchronized long bumpSequenceNumber() {
-	return ++lastSeqNum;
-    }
-
-    /**
-     * Restore the transient state of this object after recovering it
-     * from a serialization stream.  None of the arguments can be
-     * <code>null</code>.
-     * <p>
-     * Note: this method is not synchronized.  
-     * @param generator the <code>EventTypeGenerator</code> that was used
-     *        to create this EventType object originally
-     * @param monitor the object that monitors the progress of events
-     *        set by this object
-     * @param recoveredListenerPreparer the proxy preparer to use to prepare
-     *	      listeners recovered from persistent storage
-     */
-    public void restoreTransientState(EventTypeGenerator generator,  
-                                      SendMonitor monitor,
-				      ProxyPreparer recoveredListenerPreparer)
-    {
-	if (generator == null) {
-	    throw new NullPointerException("EventType.restoreTransientState:" +
-	        "Must call with a non-null generator");
-	}
-	if (monitor == null) {
-	    throw new NullPointerException("EventType.restoreTransientState:" +
-	        "Must call with a non-null monitor");
-	}
-	if (recoveredListenerPreparer == null) {
-	    throw new NullPointerException("EventType.restoreTransientState:" +
-	        "Must call with a non-null recoveredListenerPreparer");
-	}
-        synchronized (this){
-            this.generator = generator;
-            this.monitor = monitor;
-            this.recoveredListenerPreparer = recoveredListenerPreparer;
-        }
-            generator.recoverEventID(evID);
-        
-    }
-
-    /**
-     * Subclass of <code>RetryTask</code> used by <code>EventType</code>
-     * to send events.
-     */
-    private class SendTask extends RetryTask {
-	/** Max time we are willing to let a send attempt to go on for */
-	final static private long MAX_TIME = 1000 * 60 * 60 * 24; //~ 1 Day
-	
-	/** Factory used to create the <code>RemoteEvent</code> to be sent */
-	final private EventFactory eventFactory;
-
-	/** Sequence number the event should have */
-	final private long seqNum;
-
-	/** Cached event */
-	private RemoteEvent event;
-	
-	/** 
-	 * Registration sequence number of the listener/handback pair
-	 * event was built for
-	 */
-	private long eventForRegistrationNumber = -1;
-
-	/**
-	 * Simple constructor.
-	 * @param taskManager <code>TaskManager</code> this task is to be
-	 *                    put into
-	 * @param eventFactory <code>EventFactory</code> that will be used
-	 *                     to create the event to be sent
-	 * @param seqNum      the sequence number of the event
-	 */
-	private SendTask(ExecutorService taskManager, WakeupManager wakeupManager,
-			 EventFactory eventFactory, long seqNum)
-	{
-	    super(taskManager, wakeupManager);
-	    this.eventFactory = eventFactory;
-	    this.seqNum = seqNum;
-	}
-
-	// Inherit java doc from super type
-	public boolean tryOnce() {
-	    final long now = System.currentTimeMillis();
-	    if (now - startTime() > MAX_TIME)
-		return true;	// we have been trying too long, stop here
-
-	    if (!EventType.this.monitor.isCurrent())
-		return true;	// lease gone, stop here
-
-	    // Local copies of listener and handback so they won't
-	    // be clobbered by setListener calls
-	    RemoteEventListener listener;
-	    MarshalledObject handback;
-	    long registrationNumber;
-	    
-	    synchronized (EventType.this) {
-		if (!EventType.this.haveListener())
-		    return true; // No currently registered listener, stop here
-
-		listener = EventType.this.getListener();
-		if (listener == null) {
-		    return false; // There is a listener, but we can't unpack
-				  // it -- schedule a retry later
-		}
-		handback = EventType.this.handback;
-		registrationNumber = EventType.this.registrationNumber;
-	    }
-
-	    // If the handback has changed we need to create a new
-	    // event object (we approximate this test by checking the
-	    // registrationNumber
-
-	    if (event == null || 
-		eventForRegistrationNumber != registrationNumber) 
-	    {
-		event = eventFactory.createEvent(EventType.this.evID, seqNum,
-						 handback);
-		eventForRegistrationNumber = registrationNumber;
-	    }
-
-	    // Try sending 
-	    try {
-		listener.notify(event);
-		return true;
-	    } catch (Throwable t) {
-		// Classify the exception using ThrowableConstants, if
-		// it is a bad object or uncategorized (which must be
-		// a UnknownEventException) drop the event
-		// registration, if it is a bad invocation mark the
-		// try is done (since re-sending this event won't work), 
-		// but don't drop the registration.  If indefinite return 
-		// false so a retry will be scheduled.
-		final int cat = ThrowableConstants.retryable(t);
-		if (cat == ThrowableConstants.INDEFINITE) {
-		    logger.log(Levels.HANDLED,
-			       "Problem sending event -- will retry later",
-			       t);
-		    return false;
-		} else if (cat == ThrowableConstants.BAD_INVOCATION) {
-		    logger.log(Level.INFO, "Problem sending event", t);
-		    return true;
-		} else {
-		    EventType.this.monitor.definiteException(EventType.this,
-		        event, registrationNumber, t);
-		    logger.log(Level.INFO, "Problem sending event", t);
-		    return true;
-		}
-	    }
-	    
-	}
-
-    }
-}
+/*
+ * 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.norm.event;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.rmi.MarshalledObject;
+import java.rmi.RemoteException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import net.jini.core.event.RemoteEvent;
+import net.jini.core.event.RemoteEventListener;
+import net.jini.core.event.UnknownEventException;
+import net.jini.security.ProxyPreparer;
+
+import com.sun.jini.constants.ThrowableConstants;
+import com.sun.jini.logging.Levels;
+import com.sun.jini.thread.RetryTask;
+import com.sun.jini.thread.WakeupManager;
+import java.util.concurrent.ExecutorService;
+import net.jini.io.MarshalledInstance;
+
+/**
+ * Representation of an event type the supports a single registrant.
+ * The registrant, event ID, and event sequence number information
+ * portions of this object are preserved when serialized.  The send
+ * monitor, and currently scheduled event sends are not.
+ *
+ * @author Sun Microsystems, Inc.
+ */
+// $$$ I am not sure if this class does too much locking, or too little.
+// It does too little in that it does not do any locking during serialization
+// It does too much in that Norm's current locking discipline means that for
+// the most part this class does not have to worry about multiple threads
+// of control entering at one time.
+// Before we make this a general utility we have to re-think the locking
+// strategy.
+public class EventType implements Serializable {
+    private static final long serialVersionUID = 2;
+
+    /** Logger for logging messages for this class */
+    private static final Logger logger = Logger.getLogger("com.sun.jini.norm");
+
+    /**
+     * Listener registered for events of this type.  Stored in 
+     * marshalled form so object the <code>EventType</code> object can
+     * be recovered even if the listener's codebase is not available.
+     * If this field is <code>null</code>, <code>listener</code>
and 
+     * <code>handback</code> will be also.  
+     * @serial
+     */
+    private MarshalledObject marshalledListener;
+
+    /** Transient cache of listener in unmarshalled form */
+    private transient RemoteEventListener listener;
+
+    /**
+     * The proxy preparer to use to prepare a newly unmarshalled listener, or
+     * null if this instance was created using an already prepared listener,
+     * which is how instances are created initially.
+     */
+    private transient ProxyPreparer recoveredListenerPreparer;
+
+    /**
+     * Handback object associated with current listener.
+     * @serial
+     */
+    private MarshalledObject handback;
+
+    /** 
+     * Sequence number of the current listener/handback pair, incremented
+     * every time a new listener is set (even if the objects 
+     * are equivalent)
+     * @serial
+     */
+    private long registrationNumber;
+
+    /**
+     * Last event sequence number we used
+     * @serial
+     */
+    private long lastSeqNum;
+
+    /**
+     * Our event ID
+     * @serial
+     */
+    private final long evID;
+
+    /** 
+     * Object we check with to ensure leases have not expired and notify
+     * when we get a definite exception during an event send attempt.
+     * If this field is <code>null</code> generator will be also.
+     */
+    private transient SendMonitor monitor;
+
+    /** 
+     * Event type generator that created us. If this field is
+     * <code>null</code> monitor will be also.
+     */
+    private transient EventTypeGenerator generator;
+
+    /**
+     * Simple constructor.  Initially the last sequence number is set to 0.
+     * @param generator EventTypeGenerator that is creating this event type
+     * @param monitor Object which is to monitor the sending of events
+     *	      of this type
+     * @param evID event ID of this event type
+     * @param listener the listener events of this type should go to
+     * @param handback the object that should be passed to listener
+     *        as part of the event
+     * @throws IOException if the listener cannot be serialized 
+     */
+    EventType(EventTypeGenerator generator, SendMonitor monitor, long evID,
+	      RemoteEventListener listener, MarshalledObject handback)
+        throws IOException
+    {
+	if (generator == null) {
+	    throw new NullPointerException("EventType(): Must create event " +
+                "type objects with a non-null generator");
+	}
+
+	if (monitor == null) {
+	    throw new NullPointerException("EventType(): Must create event " +
+                "type objects with a non-null monitor");
+	}
+
+	this.generator = generator;
+	this.monitor = monitor;
+	this.evID = evID;
+	setLastSequenceNumber(0);
+	setListener(listener, handback);
+    }    
+
+    /** Utility method to null out listener */
+    private void clearListener() {
+	listener = null;
+	handback = null;
+	marshalledListener = null;
+    }
+
+    /**
+     * (Re)set the listener for this type of event.  Any pending
+     * events that have not yet been sent will be sent to the new
+     * listener, passing the new handback.  Setting the listener to
+     * <code>null</code> will cancel the sending of all pending
+     * events.  
+     *
+     * @param listener the listener events of this type should go to
+     * @param handback the object that should be passed to listener
+     *        as part of the event
+     * @throws IOException if listener cannot be serialized
+     */
+    public final synchronized void setListener(RemoteEventListener listener, 
+					 MarshalledObject    handback)
+        throws IOException
+    {
+	registrationNumber++;
+	
+	if (listener == null) {
+	    clearListener();
+	} else {	    
+	    marshalledListener = 
+                new MarshalledInstance(listener).convertToMarshalledObject();
+	    this.listener = listener;
+	    this.handback = handback;
+	}
+    }
+
+    /**
+     * Returns <code>true</code> if there is a listener registered for this 
+     * event type.
+     */
+    public synchronized boolean haveListener() {
+	return marshalledListener != null;
+    }
+
+    /**
+     * Convince method to get the listener.
+     * @return the listener, or <code>null</code> if the listener can't be
+     *	       unpacked or prepared, or there is no listener
+     * synchronized externally
+     */
+    private RemoteEventListener getListener() {
+	if (!haveListener()) 
+	    return null;
+            
+	if (listener != null) 
+	    return listener;
+
+	// There is a listener, but it is not unpacked yet, try to unpack
+	RemoteEventListener unpreparedListener = null;
+	try {
+	    unpreparedListener =
+		(RemoteEventListener) new MarshalledInstance(marshalledListener).get(false);
+	} catch (IOException e) {
+	    logger.log(Levels.HANDLED,
+		       "Problem unmarshalling listener -- will retry later",
+		       e);
+	    // $$$ is this really the right thing to do?
+	    // we probably really have a corrupted marshalledListener here
+	} catch (ClassNotFoundException e) {
+	    logger.log(Levels.HANDLED,
+		       "Problem unmarshalling listener -- will retry later",
+		       e);
+	}
+
+	if (unpreparedListener != null) {
+	    // Prepare the listener
+	    try {
+		listener = (RemoteEventListener)
+		    recoveredListenerPreparer.prepareProxy(unpreparedListener);
+	    } catch (RemoteException e) {
+		logger.log(Levels.HANDLED,
+			   "Problem preparing listener -- will retry later",
+			   e);
+	    } catch (SecurityException e) {
+		logger.log(Levels.HANDLED,
+			   "Problem preparing listener -- will retry later",
+			   e);
+	    }
+	}
+
+	return listener;
+    }
+
+    /**
+     * Atomically clear the current registration if its sequence
+     * number matches the passed in sequence number.  If the
+     * replacement occurs it will have the same effect as calling
+     * <code>setListener(null, null)</code>.
+     * <p>
+     * Can be used by code that needs to remove event registrations in
+     * response to exceptions thrown during event delivery without
+     * risking clobbering new registrations.
+     * @param oldSequenceNumber sequence number of the 
+     *        registration that had a problem 
+     * @return <code>true</code> if the state of the object was
+     * changed and <code>false</code> otherwise
+     * @see EventType#setListener 
+     */
+    public synchronized boolean clearListenerIfSequenceMatch(
+        long oldSequenceNumber) 
+    {
+	if (oldSequenceNumber == registrationNumber) {
+	    clearListener();
+	    return true;
+	}
+
+	return false;
+    }
+
+    /**
+     * Set the object's notion of the last sequence number.  The next event
+     * scheduled to be sent will have a sequence number one greater than
+     * the value past to this call.
+     * <p>
+     * @param seqNum value for the last sequence number
+     */
+    public final synchronized void setLastSequenceNumber(long seqNum) {
+	lastSeqNum = seqNum;
+    }
+
+    /**
+     * Return the sequence number of the last event that was scheduled
+     * to be sent.  Intended primarily for creating
+     * <code>EventRegistration</code> objects and the like.
+     */
+    public synchronized long getLastSequenceNumber () {
+	return lastSeqNum;
+    }
+    
+    /**
+     * Return the <code>long</code> that was uniquely associated with this
+     * object when it was created.
+     */
+    public long getEventID() {
+	return evID;
+    }
+
+    /**
+     * Schedule the sending of an event.  This event will be sent to
+     * the currently registered listener.  If the listener changes
+     * before the the event is successfully sent the event will be sent
+     * to the new listener.  If the current listener is
+     * <code>null</code> this call will have no affect aside from
+     * incrementing the sequence number.
+     * @param factory an object that will be used to create the
+     * <code>Event</code> object when necessary
+     * @return the sequence number assigned to the event
+     * @throws IllegalStateException if this method is called
+     *         after the object has be deserialized and before
+     *         <code>restoreTransientState</code> has been called
+     * @see EventType#restoreTransientState
+     */
+    public synchronized long sendEvent(EventFactory factory) {
+	if (generator == null) {
+	    // Have not had our state restored, complain
+	    throw new IllegalStateException("EventType.sendEvent:" +
+	        "called before state was fully restored");
+	}
+
+	// Even if there is no listener, an event has occurred, so
+	// increment the sequence number (note this a stronger
+	// guarantee that the Jini Distributed Event Specification,
+	// but one that is required by the LRS spec).
+	lastSeqNum++;
+
+	// If we don't have a listener we don't need do anything else
+	if (!haveListener())
+	    return lastSeqNum;
+	
+	final ExecutorService mgr = generator.getExecutorService();
+	final WakeupManager wMgr = generator.getWakeupManager();
+	mgr.execute(new SendTask(mgr, wMgr, factory, lastSeqNum));
+	
+	return lastSeqNum;
+    }
+
+    /**
+     * Increment the sequence number and return the result. This
+     * method is useful if an event occurs that needs to be noted
+     * but from some reason it is impossible to deliver the event.
+     *
+     * @return the new value for the sequence number
+     */
+    public synchronized long bumpSequenceNumber() {
+	return ++lastSeqNum;
+    }
+
+    /**
+     * Restore the transient state of this object after recovering it
+     * from a serialization stream.  None of the arguments can be
+     * <code>null</code>.
+     * <p>
+     * Note: this method is not synchronized.  
+     * @param generator the <code>EventTypeGenerator</code> that was used
+     *        to create this EventType object originally
+     * @param monitor the object that monitors the progress of events
+     *        set by this object
+     * @param recoveredListenerPreparer the proxy preparer to use to prepare
+     *	      listeners recovered from persistent storage
+     */
+    public void restoreTransientState(EventTypeGenerator generator,  
+                                      SendMonitor monitor,
+				      ProxyPreparer recoveredListenerPreparer)
+    {
+	if (generator == null) {
+	    throw new NullPointerException("EventType.restoreTransientState:" +
+	        "Must call with a non-null generator");
+	}
+	if (monitor == null) {
+	    throw new NullPointerException("EventType.restoreTransientState:" +
+	        "Must call with a non-null monitor");
+	}
+	if (recoveredListenerPreparer == null) {
+	    throw new NullPointerException("EventType.restoreTransientState:" +
+	        "Must call with a non-null recoveredListenerPreparer");
+	}
+        synchronized (this){
+            this.generator = generator;
+            this.monitor = monitor;
+            this.recoveredListenerPreparer = recoveredListenerPreparer;
+        }
+            generator.recoverEventID(evID);
+        
+    }
+
+    /**
+     * Subclass of <code>RetryTask</code> used by <code>EventType</code>
+     * to send events.
+     */
+    private class SendTask extends RetryTask {
+	/** Max time we are willing to let a send attempt to go on for */
+	final static private long MAX_TIME = 1000 * 60 * 60 * 24; //~ 1 Day
+	
+	/** Factory used to create the <code>RemoteEvent</code> to be sent */
+	final private EventFactory eventFactory;
+
+	/** Sequence number the event should have */
+	final private long seqNum;
+
+	/** Cached event */
+	private RemoteEvent event;
+	
+	/** 
+	 * Registration sequence number of the listener/handback pair
+	 * event was built for
+	 */
+	private long eventForRegistrationNumber = -1;
+
+	/**
+	 * Simple constructor.
+	 * @param taskManager <code>TaskManager</code> this task is to be
+	 *                    put into
+	 * @param eventFactory <code>EventFactory</code> that will be used
+	 *                     to create the event to be sent
+	 * @param seqNum      the sequence number of the event
+	 */
+	private SendTask(ExecutorService taskManager, WakeupManager wakeupManager,
+			 EventFactory eventFactory, long seqNum)
+	{
+	    super(taskManager, wakeupManager);
+	    this.eventFactory = eventFactory;
+	    this.seqNum = seqNum;
+	}
+
+	// Inherit java doc from super type
+	public boolean tryOnce() {
+	    final long now = System.currentTimeMillis();
+	    if (now - startTime() > MAX_TIME)
+		return true;	// we have been trying too long, stop here
+
+	    if (!EventType.this.monitor.isCurrent())
+		return true;	// lease gone, stop here
+
+	    // Local copies of listener and handback so they won't
+	    // be clobbered by setListener calls
+	    RemoteEventListener listener;
+	    MarshalledObject handback;
+	    long registrationNumber;
+	    
+	    synchronized (EventType.this) {
+		if (!EventType.this.haveListener())
+		    return true; // No currently registered listener, stop here
+
+		listener = EventType.this.getListener();
+		if (listener == null) {
+		    return false; // There is a listener, but we can't unpack
+				  // it -- schedule a retry later
+		}
+		handback = EventType.this.handback;
+		registrationNumber = EventType.this.registrationNumber;
+	    }
+
+	    // If the handback has changed we need to create a new
+	    // event object (we approximate this test by checking the
+	    // registrationNumber
+
+	    if (event == null || 
+		eventForRegistrationNumber != registrationNumber) 
+	    {
+		event = eventFactory.createEvent(EventType.this.evID, seqNum,
+						 handback);
+		eventForRegistrationNumber = registrationNumber;
+	    }
+
+	    // Try sending 
+	    try {
+		listener.notify(event);
+		return true;
+	    } catch (Throwable t) {
+		// Classify the exception using ThrowableConstants, if
+		// it is a bad object or uncategorized (which must be
+		// a UnknownEventException) drop the event
+		// registration, if it is a bad invocation mark the
+		// try is done (since re-sending this event won't work), 
+		// but don't drop the registration.  If indefinite return 
+		// false so a retry will be scheduled.
+		final int cat = ThrowableConstants.retryable(t);
+		if (cat == ThrowableConstants.INDEFINITE) {
+		    logger.log(Levels.HANDLED,
+			       "Problem sending event -- will retry later",
+			       t);
+		    return false;
+		} else if (cat == ThrowableConstants.BAD_INVOCATION) {
+		    logger.log(Level.INFO, "Problem sending event", t);
+		    return true;
+		} else {
+		    EventType.this.monitor.definiteException(EventType.this,
+		        event, registrationNumber, t);
+		    logger.log(Level.INFO, "Problem sending event", t);
+		    return true;
+		}
+	    }
+	    
+	}
+
+    }
+}

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/event/EventTypeGenerator.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/event/EventTypeGenerator.java?rev=1634322&r1=1634321&r2=1634322&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/event/EventTypeGenerator.java
(original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/event/EventTypeGenerator.java
Sun Oct 26 13:17:28 2014
@@ -48,7 +48,7 @@ public class EventTypeGenerator implemen
     private long nextEvID = 1;
 
     /**
-     * Task manager used to send events
+     * ExecutorService used to send events
      */
     private transient ExecutorService taskManager = 
             new ThreadPoolExecutor(
@@ -120,10 +120,10 @@ public class EventTypeGenerator implemen
     }
 
     /**
-     * Return the task manager that <code>EventType</code> objects created
+     * Return the ExecutorService that <code>EventType</code> objects created
      * by this generator should use to send their events.
      */
-    ExecutorService getTaskManager() {
+    ExecutorService getExecutorService() {
 	return taskManager;
     }
 



Mime
View raw message