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/10/26 14:17:31 UTC
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...
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;
}