Package org.rioproject.impl.event

Source Code of org.rioproject.impl.event.BasicEventConsumer$ClientNotification

/*
* 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 com.sun.jini.config.Config;
import com.sun.jini.proxy.BasicProxyTrustVerifier;
import net.jini.config.Configuration;
import net.jini.config.EmptyConfiguration;
import net.jini.core.entry.Entry;
import net.jini.core.event.EventRegistration;
import net.jini.core.event.RemoteEvent;
import net.jini.core.event.UnknownEventException;
import net.jini.core.lease.Lease;
import net.jini.core.lookup.ServiceID;
import net.jini.core.lookup.ServiceItem;
import net.jini.export.Exporter;
import net.jini.security.BasicProxyPreparer;
import net.jini.security.ProxyPreparer;
import net.jini.security.TrustVerifier;
import net.jini.security.proxytrust.ServerProxyTrust;
import org.rioproject.impl.config.ExporterConfig;
import org.rioproject.event.*;
import org.rioproject.impl.util.ThrowableUtil;
import org.rioproject.impl.util.TimeConstants;
import org.rioproject.util.TimeUtil;
import org.rioproject.impl.watch.StopWatch;
import org.rioproject.impl.watch.Watch;
import org.rioproject.impl.watch.WatchDataSourceRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.rmi.MarshalledObject;
import java.rmi.RemoteException;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* The BasicEventConsumer is a helper class that manages the
* discovery of {@link org.rioproject.event.EventProducer} instances that provide support for
* user defined events. The BasicEventConsumer is to be used as a
* local (within a JVM) utility, managing the discovery, event registration and
* leasing of {@link net.jini.core.event.EventRegistration} objects on behalf of
* client(s). In this manner, clients wishing to easily register (subscribe) for the
* notification of an event in the distributed system need not be overly
* concerned with the underlying semantics and management of event
* registrations, leases and events.
*
* @author Dennis Reedy
*/
public class BasicEventConsumer implements EventConsumer, ServerProxyTrust  {
    /** The remote ref (e.g. stub or dynamic proxy) for the BasicEventConsumer */
    private EventConsumer eventConsumer;
    /** The Exporter for the BasicEventConsumer */
    private Exporter exporter;
    /** The proxyPreparer for EventRegistration */
    private ProxyPreparer eventLeasePreparer;
    protected final List<RemoteServiceEventListener> eventSubscribers =
        Collections.synchronizedList(new ArrayList<RemoteServiceEventListener>());
    protected final Hashtable<ServiceID, EventLeaseManager> leaseTable = new Hashtable<ServiceID, EventLeaseManager>();
    protected final Map<Long, EventRegistration> eventRegistrationTable = new Hashtable<Long, EventRegistration>();
    protected EventDescriptor edTemplate;
    protected int received = 0;
    protected long sktime, ektime;
    protected MarshalledObject handback = null;
    /** Default Lease duration is 5 minutes */
    protected static final long DEFAULT_LEASE_DURATION = TimeConstants.FIVE_MINUTES;
    protected long leaseDuration = DEFAULT_LEASE_DURATION;
    protected StopWatch responseWatch = null;
    protected WatchDataSourceRegistry watchRegistry = null;
    /** Number of retries to attempt to connect to an EventProducer */
    private int connectRetries;
    private static final int DEFAULT_CONNECT_RETRY_COUNT = 3;
    /** How long to wait between retries */
    private long retryWait;
    private static final long DEFAULT_RETRY_WAIT = TimeConstants.ONE_SECOND;
    public static final String RESPONSE_WATCH = "Response Time";
    static final String COMPONENT = "org.rioproject.event";
    /** The Logger */
    static Logger logger = LoggerFactory.getLogger(BasicEventConsumer.class);
    private final Configuration config;
    private final ExecutorService service;

    /**
     * Create a BasicEventConsumer with an EventDescriptor
     *
     * @param edTemplate The EventDescriptor template
     *
     * @throws Exception If the BasicEventConsumer cannot be created
     */
    public BasicEventConsumer(final EventDescriptor edTemplate) throws Exception {
        this(edTemplate, null, null, null);
    }

    /**
     * Create a BasicEventConsumer with a RemoteServiceEventListener
     *
     * @param listener The RemoteServiceEventListener
     *
     * @throws Exception If the BasicEventConsumer cannot be created
     */
    public BasicEventConsumer(final RemoteServiceEventListener listener) throws Exception {
        this(null, listener, null, null);
    }

    /**
     * Create a BasicEventConsumer with an EventDescriptor and a
     * RemoteServiceEventListener
     *
     * @param edTemplate The EventDescriptor template
     * @param listener The RemoteServiceEventListener
     *
     * @throws Exception If the BasicEventConsumer cannot be created
     */
    public BasicEventConsumer(final EventDescriptor edTemplate, final RemoteServiceEventListener listener)
        throws Exception {
        this(edTemplate, listener, null, null);
    }

    /**
     * Create a BasicEventConsumer with an EventDescriptor and a
     * RemoteServiceEventListener
     *
     * @param edTemplate The EventDescriptor template
     * @param listener The RemoteServiceEventListener
     * @param config Configuration object
     *
     * @throws Exception If the BasicEventConsumer cannot be created
     */
    public BasicEventConsumer(final EventDescriptor edTemplate,
                              final RemoteServiceEventListener listener,
                              final Configuration config) throws Exception {
        this(edTemplate, listener, null, config);
    }

    /**
     * Create a BasicEventConsumer with an EventDescriptor, a
     * RemoteServiceEventListener, and a MarshalledObject to be used as a
     * handback
     *
     * @param edTemplate The EventDescriptor template
     * @param listener The RemoteServiceEventListener
     * @param handback The MarshalledObject to be used as a handback
     * @param config Configuration object
     *
     * @throws Exception If the BasicEventConsumer cannot be created
     */                                 
    public BasicEventConsumer(final EventDescriptor edTemplate,
                              final RemoteServiceEventListener listener,
                              final MarshalledObject handback,
                              final Configuration config) throws Exception {
        ProxyPreparer basicLeasePreparer = new BasicProxyPreparer();


        if(config == null)
            this.config = EmptyConfiguration.INSTANCE;
        else
            this.config = config;

        leaseDuration = Config.getLongEntry(this.config,
                                            COMPONENT,
                                            "eventLeaseDuration",
                                            DEFAULT_LEASE_DURATION, //default
                                            1000*60,                // min
                                            Long.MAX_VALUE);        // max

        exporter = ExporterConfig.getExporter(this.config, COMPONENT, "eventConsumerExporter");

        eventLeasePreparer = (ProxyPreparer)this.config.getEntry(COMPONENT,
                                                                 "eventLeasePreparer",
                                                                 ProxyPreparer.class,
                                                                 basicLeasePreparer);
        connectRetries = Config.getIntEntry(this.config,
                                            COMPONENT,
                                            "connectRetries",
                                            DEFAULT_CONNECT_RETRY_COUNT, // default
                                            0,                           // min
                                            5);                          // max

        retryWait = Config.getLongEntry(this.config,
                                        COMPONENT,
                                        "retryWait",
                                        DEFAULT_RETRY_WAIT,  // default
                                        0,                   // min
                                        Long.MAX_VALUE);     // max

        eventConsumer = (EventConsumer)exporter.export(this);
        //refQueue = new ReferenceQueue();
        this.edTemplate = edTemplate;
        if(edTemplate!=null)
            logger.trace("Create BasicEventConsumer for EventDescriptor : {}", edTemplate.toString());
        this.handback = handback;
        if(listener != null)
            eventSubscribers.add(listener);
        service = Executors.newCachedThreadPool();
    }

    /**
     * The terminate method will de-register for event notifications across all
     * discovered EventProducer instances. Invocation of this method will result
     * in the cancellation of any leases involved with event registration and
     * the removal from the event notification pool. This method will also
     * unexport the EventConsumer, removing it from the RMI runtime. This method
     * will also destroy the response time watch if it was created
     */
    public void terminate() {
        if(service!=null)
            service.shutdownNow();
        /* Deregister all listeners */
        RemoteServiceEventListener[] listeners = getListeners();
        for (RemoteServiceEventListener listener : listeners) {
            try {
                deregister(listener);
            } catch (Exception e) {
                logger.warn("Deregistering EventConsumer", e);
            }
        }
        /* Destroy the watch */
        destroyWatch();
        /* If we exported, unexport, use force=true */
        if(eventConsumer != null) {
            try {
                exporter.unexport(true);
            } catch(IllegalStateException e) {
                logger.warn("EventConsumer not unexported", e);
            }
        }
    }

    /**
     * Register a RemoteServiceEventListener to this EventConsumer. If there are
     * no RemoteServiceEventListener instances registered events will be dropped
     * by this BasicEventConsumer. Each registered RemoteServiceEventListener
     * will be notified for each event received.
     *
     * @param listener The RemoteServiceEventListener
     * @return true if the RemoteServiceEventListener has been added
     */
    public boolean register(final RemoteServiceEventListener listener) {
        return (register(listener, null));
    }

    /**
     * Register a RemoteServiceEventListener to this EventConsumer with a
     * MarshalledObject handback object. If there are no
     * RemoteServiceEventListener instances registered events will be dropped by
     * this BasicEventConsumer.
     *
     * Each registered RemoteServiceEventListener will be notified for each
     * event received
     *
     * @param listener The RemoteServiceEventListener
     * @param handback The MarshalledObject to be used as a handback
     * @return true if the RemoteServiceEventListener has been added
     */
    public boolean register(final RemoteServiceEventListener listener, final MarshalledObject handback) {
        this.handback = handback;
        boolean added = eventSubscribers.add(listener);
        return (added);
    }

    /**
     * De-registers a registered RemoteServiceEventListener from this
     * EventConsumer
     *
     * @param listener The RemoteServiceEventListener
     * @return true if the RemoteServiceEventListener was removed
     */
    public boolean deregister(final RemoteServiceEventListener listener) {
        return(removeListener(listener));
    }

    /**
     * Create a response time watch for this EventConsumer, which will track the
     * response time for event consumers, measured by how long the response time
     * takes
     *
     * @param watchRegistry The WatchDataSourceRegistry to register the watch
     *
     * @return The Watch
     */
    public Watch createWatch(final WatchDataSourceRegistry watchRegistry) {
        if(watchRegistry == null)
            throw new IllegalArgumentException("watchRegistry is null");
        if(responseWatch!=null)
            return responseWatch;
        responseWatch = new StopWatch(RESPONSE_WATCH, config);
        this.watchRegistry = watchRegistry;
        watchRegistry.register(responseWatch);
        return responseWatch;
    }

    /**
     * Destroys the response time watch. Once this method is called the response
     * time watch will be rendered useless
     */
    public void destroyWatch() {
        if(watchRegistry != null) {
            watchRegistry.deregister(responseWatch);
        }
        if(responseWatch != null) {
            try {
                responseWatch.getWatchDataSource().clear();
                responseWatch.getWatchDataSource().close();
            } catch(RemoteException e) {
                logger.warn("RemoteException Destroying Watch", e);
            }
        }
        responseWatch = null;
    }

    /**
     * Get the response time watch for this EventConsumer
     *
     * @return The response time watch for this EventConsumer
     */
    public Watch getWatch() {
        return (responseWatch);
    }

    /**
     * Given a ServiceItem this method checks to see if the ServiceItem contains
     * a proxy of type EventProducer, performs event registration and ensures the
     * Lease contained in the event registration is managed by a
     * LeaseRenewalManager
     *
     * @param item The ServiceItem
     * @return The {@link net.jini.core.event.EventRegistration}, or null if the
     * service is not an {@link org.rioproject.event.EventProducer} or the {@link EventDescriptor}
     * template the BasicEventConsumer was started with cannot be matched
     *
     * @throws IllegalArgumentException if the item parameter is null
     */
    public EventRegistration register(final ServiceItem item) {
        if(item==null)
            throw new IllegalArgumentException("item is null");

        if(edTemplate==null)
            throw new IllegalStateException("An EventDescriptor template has not " +
                                            "been set when creating the " +
                                            "BasicEventConsumer, this utility " +
                                            "cannot determine the EventDescriptor " +
                                            "to register for. Check your use " +
                                            "of the BasicEventConsumer and " +
                                            "construct it with an EventDescriptor");

        if(!(item.service instanceof EventProducer)) {
            logger.trace("Service is not an EventProducer");
            return (null);
        }

        EventDescriptor eDesc = getDescriptor(item.attributeSets, edTemplate);
        if(eDesc == null) {
            logger.debug("Cannot get EventDescriptor match");
            logger.trace("ServiceItem.service ClassLoader {}, EventDescriptor {}, EventDescriptor ClassLoader {}",
                         item.service.getClass().getClassLoader().toString(),
                         edTemplate.toString(),
                         edTemplate.getClass().getClassLoader().toString());
            return (null);
        }

        EventProducer producer = (EventProducer)item.service;
        return register(producer, eDesc, item.serviceID);
    }

    /**
     * Register for notification of event from an {@link EventProducer}.
     *
     * @param eventProducer The EventProducer, must not be null
     * @param eventDesc The EventDescriptor, must not be null
     * @param serviceID The serviceID of the EventProducer to register
     * @return The {@link net.jini.core.event.EventRegistration}, or null if the
     * service is not an {@link EventProducer} or the {@link EventDescriptor}
     * template the BasicEventConsumer was started with cannot be matched
     *
     * @throws IllegalArgumentException if any og the parameters are null
     */
    public EventRegistration register(final EventProducer eventProducer,
                                      final EventDescriptor eventDesc,
                                      final ServiceID serviceID) {
        if(eventProducer==null)
            throw new IllegalArgumentException("eventProducer is null");
        if(eventDesc==null)
            throw new IllegalArgumentException("eventDesc is null");
        if(serviceID==null)
            throw new IllegalArgumentException("serviceID is null");

        if(leaseTable.containsKey(serviceID)) {
            logger.trace("Already registered to EventProducer");
            return eventRegistrationTable.get(eventDesc.eventID);
        }

        EventRegistration eReg = null;
        Lease lease = connect(eventProducer, eventDesc);
        if(lease!=null) {
            EventLeaseManager eventLeaseManager = new EventLeaseManager(eventProducer, lease, eventDesc);
            leaseTable.put(serviceID, eventLeaseManager);
            service.submit(eventLeaseManager);
            eReg = eventRegistrationTable.get(eventDesc.eventID);
        }
        return (eReg);
    }

    /**
     * Connect to the EventProducer and get a Lease
     *
     * @param producer The EventProducer
     * @param eDesc The EventDescriptor
     *
     * @return The Lease for the @link net.jini.core.event.EventRegistration}
     */
    Lease connect(final EventProducer producer, final EventDescriptor eDesc) {
        Lease lease = null;
        for(int i=0; i<connectRetries; i++) {
            try {
                EventRegistration eReg = producer.register(eDesc, eventConsumer, handback, leaseDuration);
                eventRegistrationTable.put(eDesc.eventID, eReg);
                lease = (Lease)eventLeasePreparer.prepareProxy(eReg.getLease());
                long leaseTime = lease.getExpiration() - System.currentTimeMillis();
                if(leaseTime>0) {
                    logger.trace("Event Registration Lease acquired and prepared. Duration={} ({} seconds)",
                                 leaseTime, (leaseTime / 1000));
                    break;
                } else {
                    logger.warn("Invalid Lease time [{}], retry count [{}]", leaseTime, i);
                    try {
                        lease.cancel();
                    } catch(Exception e ) {
                        logger.trace("Cancelling Lease with invalid lease time", e);
                    }
                    if(retryWait>0) {
                        try {
                            Thread.sleep(retryWait);
                        } catch(InterruptedException ie) {
                            /* should not happen */
                        }
                    }
                }

            } catch(Exception e) {
                /* Determine if we should even try to reconnect */
                if(!ThrowableUtil.isRetryable(e)) {
                    logger.warn("Unrecoverable Exception getting EventRegistration for {}, {}: {}",
                                eDesc.toString(), e.getClass().getName(), e.getMessage());
                    logger.trace("Unrecoverable Exception getting EventRegistration for {}", eDesc.toString(), e);
                    break;
                } else {
                    if(retryWait>0) {
                        try {
                            Thread.sleep(retryWait);
                        } catch(InterruptedException ignore) {
                            /* ignore */
                        }
                    }
                }
            }
        }
        return (lease);
    }

    /**
     * Returns the source object of an EventRegistration given an event ID
     *
     * @param eventID The eventID
     * @return If found, returns the source object associated with the
     * eventID, otherwise returns null
     */
    public Object getEventRegistrationSource(final long eventID) {
        EventRegistration eReg = eventRegistrationTable.get(eventID);
        Object source = null;
        if(eReg!=null)
            source = eReg.getSource();
        return (source);
    }

    /**
     * This method handles the cleanup for removing a registration from a
     * EventProducer instance
     *
     * @param serviceID The serviceID of the EventProducer to deregister
     *
     * @throws IllegalArgumentException if the serviceID parameter is null
     */
    public void deregister(final ServiceID serviceID) {
        deregister(serviceID, true);
    }

    /**
     * This method handles the cleanup for removing a registration from a
     * EventProducer instance
     *
     * @param serviceID The serviceID of the EventProducer to deregister
     * @param disconnect Whether to explicitly cancel the lease with the
     * EventProducer, or just let the least time out
     *
     * @throws IllegalArgumentException if the serviceID parameter is null
     */
    public void deregister(final ServiceID serviceID, final boolean disconnect) {
        if(serviceID==null)
            throw new IllegalArgumentException("serviceID is null");
        EventLeaseManager elm = leaseTable.remove(serviceID);
        if(elm != null) {
            try {
                elm.drop(disconnect);
            } catch(Exception e) {
                /* ignore */
            }
        }
    }

    /**
     * Remote event notification. This method is called by an EventProducer to
     * notify the RemoteEventListener of a state change through a RemoteEvent
     *
     * @throws UnknownEventException If the RemoteEvent cannot be downcast to a
     * RemoteServiceEvent
     */
    public void notify(final RemoteEvent rEvent)throws UnknownEventException {
        if(!(rEvent instanceof RemoteServiceEvent))
            throw new UnknownEventException("Unsupported event class");
        RemoteServiceEvent rsEvent = (RemoteServiceEvent)rEvent;
        service.submit(new ClientNotification(rsEvent));
    }

    /**
     * Returns a {@link net.jini.security.TrustVerifier} which can be used to verify
     * that a given proxy to this event consumer can be trusted
     */
    public TrustVerifier getProxyVerifier() {
        return (new BasicProxyTrustVerifier(eventConsumer));
    }

    /**
     * Method to return a matching EventDescriptor from a service's set of
     * attributes <br>
     *
     * @param attrs Array of attributes
     * @param template The EventDescriptor template
     *
     * @return An EventDescriptor if found or null if no match
     */
    protected EventDescriptor getDescriptor(final Entry[] attrs, final EventDescriptor template) {
        EventDescriptor matchedDescriptor = null;
        /* Traverse the attribute collection, for each EventDescriptor
         * attribute, first check if the attribute has a "matches" method. If it
         * does invoke the method to determine 'match-ability' */
        for (Entry attr : attrs) {
            if (attr instanceof EventDescriptor) {
                EventDescriptor ed = (EventDescriptor) attr;
                try {
                    ed.getClass().getMethod("matches", EventDescriptor.class);
                } catch (NoSuchMethodException e) {
                    logger.warn("Rio version mismatch, {} missing matches method", EventDescriptor.class.getName(), e);
                    return (null);
                }
                if (ed.matches(template)) {
                    matchedDescriptor = ed;
                    break;
                }
            }
        }
        logger.trace("Matched [{}] ? {}", template.toString(), (matchedDescriptor==null?"NO":"YES"));
        return (matchedDescriptor);
    }

    /**
     * Convenience method to print statistics for every thousand events sent.
     * This method will only print result if the Logger has it's Level set to
     * FINEST
     */
    protected void printStats() {
        if(!logger.isTraceEnabled())
            return;
        if(received == 0)
            sktime = System.currentTimeMillis();
        int m = received % 1000;
        if(m == 0 && received > 0) {
            ektime = System.currentTimeMillis();
            float tmp = (ektime - sktime) / 1000.f;
            logger.trace(String.format("Recvd [%d], \t[1000/%f]\t[%f/Second]", received, tmp, 1000.f/tmp));
            sktime = System.currentTimeMillis();
        }
    }

    private boolean removeListener(final RemoteServiceEventListener l) {
        boolean removed = eventSubscribers.remove(l);
        if(removed) {
            if(eventSubscribers.isEmpty()) {
                List<ServiceID> keyList = new ArrayList<ServiceID>();
                for(Enumeration<ServiceID> e = leaseTable.keys(); e.hasMoreElements();) {
                    keyList.add(e.nextElement());
                }
                for (ServiceID sid : keyList) {
                    deregister(sid);
                }
            }
        }
        return (removed);
    }

    /**
     * Override finalize to ensure we unexport ourselves. This is needed if
     * @throws Throwable
     */
    protected void finalize() throws Throwable {
        terminate();
        super.finalize();
    }

    /**
     * Get all registered RemoteServiceEventListeners
     *
     * @return An array of all registered RemoteServiceEventListener objects
     */
    protected RemoteServiceEventListener[] getListeners() {
        return eventSubscribers.toArray(new RemoteServiceEventListener[eventSubscribers.size()]);
    }

    /**
     * Notify client asynchronously
     */
    class ClientNotification implements Runnable {
        RemoteServiceEvent rsEvent;

        ClientNotification(RemoteServiceEvent rsEvent) {
            this.rsEvent = rsEvent;
        }

        public void run() {
            long startTime = System.currentTimeMillis();
            logger.trace("Received RemoteServiceEvent [{}], Number of subscribers : {}",
                         rsEvent.getClass().getName(), eventSubscribers.size());

            RemoteServiceEventListener[] listeners = getListeners();
            for (RemoteServiceEventListener listener : listeners) {
                logger.trace("Notify subscriber [{}]", listener.getClass().getName());
                listener.notify(rsEvent);
                received++;
                printStats();
            }

            if(responseWatch != null) {
                long now = System.currentTimeMillis();
                long elapsed = now - startTime;
                responseWatch.setElapsedTime(elapsed, now);
            }
        }
    }

    /**
     * Use customized Lease renewal to manage leases to EventRegistration
     * leases. This is needed because leases constructed to EventProducer
     * instances may be shorter then 5 minutes. If we use LeaseRenewalManager
     * and the leases are shorter then 5 minutes, then after 5 minutes the lease
     * is allowed to expire.
     */
    class EventLeaseManager implements Runnable {
        private final long leaseTime;
        private boolean keepAlive = true;
        private final EventProducer producer;
        private Lease lease;
        private final EventDescriptor eDesc;

        EventLeaseManager(final EventProducer producer, final Lease lease, final EventDescriptor eDesc) {
            this.producer = producer;
            this.lease = lease;
            this.leaseTime = lease.getExpiration() - System.currentTimeMillis();
            this.eDesc = eDesc;
            logger.trace("Created EventLeaseManager, EventDescriptor={}, Lease Time={} seconds",
                         eDesc.toString(), (leaseTime / 1000));
        }

        void drop(boolean disconnect) {
            keepAlive = false;
            if(disconnect) {
                try {
                    lease.cancel();
                } catch(Exception ignore) {
                    /* ignore */
                }
            }
        }

        public void run() {
            while (keepAlive) {
                try {
                     long waitTillRenew = TimeUtil.computeLeaseRenewalTime(leaseTime);
                    logger.trace("Wait to renew {} lease for {}", eDesc.toString(), TimeUtil.format(waitTillRenew));
                    Thread.sleep(waitTillRenew);
                } catch(InterruptedException ignore) {
                    /* ignore */
                }
                if(lease != null) {
                    try {
                        logger.trace("Renew lease for {}", eDesc.toString());
                        lease.renew(leaseTime);
                    } catch(Exception e) {
                        /* Determine if we should even try to reconnect */
                        if(!ThrowableUtil.isRetryable(e)) {
                            keepAlive = false;
                            logger.warn("EventLeaseManager, Unrecoverable Exception renewing Lease, dropping Lease renewal for {}",
                                        eDesc.toString());
                            logger.trace("Unrecoverable Exception renewing Lease for {}", eDesc.toString(), e);
                        }
                        if(keepAlive) {
                            logger.trace("Attempt to reconnect to producer {} for event {}",
                                         producer.toString(), eDesc.toString());
                            lease = connect(producer, eDesc);
                            if(lease==null) {
                                logger.warn("EventLeaseManager, Unable to obtain Lease, dropping Lease renewal for {}",
                                           eDesc.toString());
                                keepAlive = false;
                            } else {
                                logger.trace("Reconnect succeeded to producer {} for event {}",
                                             producer.toString(), eDesc.toString());
                            }
                        }
                    }
                }
            }
            logger.trace("EventLeaseManager {} leaving", eDesc.toString());
        }
    }
}
TOP

Related Classes of org.rioproject.impl.event.BasicEventConsumer$ClientNotification

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.