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; }
