/*
* Copyright to the original author or authors.
*
* Licensed 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 org.rioproject.impl.event;
import net.jini.config.Configuration;
import net.jini.core.event.RemoteEventListener;
import net.jini.core.event.UnknownEventException;
import org.rioproject.event.EventDescriptor;
import org.rioproject.event.RemoteServiceEvent;
import org.rioproject.impl.service.ServiceResource;
import org.rioproject.impl.util.ThrowableUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.rmi.MarshalledObject;
import java.rmi.RemoteException;
import static java.lang.String.format;
/**
* The <code>DispatchEventHandler</code> provides an implementation of an
* <code>EventHandler</code> which supports the notification of events to all
* registered event listeners with a valid lease.
* <p>
* Event registrations are leased and explicitly checked prior to each
* notification being sent to the remote event listener
* <p>
* The sequence number for events is incremented after each subsequent fire
* invocation.
*
* @author Dennis Reedy
*/
public class DispatchEventHandler extends AbstractEventHandler {
static Logger logger = LoggerFactory.getLogger(DispatchEventHandler.class);
/**
* Construct a DispatchEventHandler with an EventDescriptor and default
* lease maximum and time allocation
*
* @param descriptor The EventDescriptor
*
* @throws IOException If a landlord lease manager cannot be created
*/
public DispatchEventHandler(EventDescriptor descriptor) throws IOException {
super(descriptor);
}
/**
* Construct a DispatchEventHandler with an EventDescriptor and a
* Configuration object
*
* @param descriptor The EventDescriptor
* @param config The configuration object
*
* @throws IOException If a landlord lease manager cannot be created
*/
public DispatchEventHandler(EventDescriptor descriptor, Configuration config) throws IOException {
super(descriptor, config);
}
/**
* Implement the <code>fire</code> method from <code>EventHandler</code>
*/
public void fire(RemoteServiceEvent event) {
event.setEventID(descriptor.eventID);
event.setSequenceNumber(sequenceNumber);
ServiceResource[] resources = resourceMgr.getServiceResources();
if(logger.isTraceEnabled())
logger.trace(format("DispatchEventHandler: notify [%d] listeners " +
"with event [%s]", resources.length,
event.getClass().getName()));
for (ServiceResource sr : resources) {
EventRegistrationResource er =
(EventRegistrationResource) sr.getResource();
if (!landlord.ensure(sr)) {
if (logger.isTraceEnabled())
logger.trace(format("DispatchEventHandler.fire() Could not ensure " +
"lease for ServiceResource " +
"[%s] resources count now : %d",
er.getListener().getClass().getName(),
resourceMgr.getServiceResources().length));
try {
resourceMgr.removeResource(sr);
landlord.remove(sr);
} catch (Exception e) {
if (logger.isTraceEnabled())
logger.trace("Removing Resource and Cancelling Lease", e);
}
continue;
}
try {
RemoteEventListener listener = er.getListener();
MarshalledObject handback = er.getHandback();
event.setHandback(handback);
t0 = System.currentTimeMillis();
listener.notify(event);
t1 = System.currentTimeMillis();
sendTime = t1 - t0;
if (responseWatch != null)
responseWatch.setElapsedTime(sendTime, t1);
sent++;
printStats();
} catch (UnknownEventException uee) {
if (logger.isTraceEnabled())
logger.trace(format("UnknownEventException for EventDescriptor [%s]", descriptor.toString()), uee);
/* We are allowed to cancel the lease here */
try {
resourceMgr.removeResource(sr);
landlord.cancel(sr.getCookie());
} catch (Exception e) {
if (logger.isTraceEnabled())
logger.warn("Removing resource and cancelling Lease", e);
}
} catch (RemoteException re) {
if (logger.isTraceEnabled())
logger.trace(format("fire() for EventDescriptor [%s]", descriptor.toString()), re);
/* Cancel the Lease if the EventConsumer is unreachable */
if(!ThrowableUtil.isRetryable(re)) {
try {
resourceMgr.removeResource(sr);
landlord.cancel(sr.getCookie());
} catch (Exception e) {
if (logger.isTraceEnabled())
logger.trace("Removing resource and cancelling Lease", e);
}
}
}
}
sequenceNumber++;
}
}