Package org.rioproject.eventcollector.service

Source Code of org.rioproject.eventcollector.service.AbstractEventManager$ServiceFaultListener

/*
* 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.eventcollector.service;

import net.jini.core.entry.Entry;
import net.jini.core.event.RemoteEvent;
import net.jini.core.event.UnknownEventException;
import net.jini.core.lookup.ServiceID;
import net.jini.core.lookup.ServiceItem;
import net.jini.core.lookup.ServiceTemplate;
import net.jini.lease.LeaseRenewalManager;
import net.jini.lookup.LookupCache;
import net.jini.lookup.ServiceDiscoveryEvent;
import net.jini.lookup.ServiceDiscoveryManager;
import org.rioproject.impl.event.BasicEventConsumer;
import org.rioproject.event.EventDescriptor;
import org.rioproject.event.RemoteServiceEvent;
import org.rioproject.event.RemoteServiceEventListener;
import org.rioproject.impl.client.ServiceDiscoveryAdapter;
import org.rioproject.impl.util.ThrowableUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* Provides basic support for an {@code EventManager}.
*
* @author Dennis Reedy
*/
public abstract class AbstractEventManager implements RemoteServiceEventListener, EventManager {
    private static final Logger logger = LoggerFactory.getLogger(AbstractEventManager.class.getName());
    private BlockingQueue<RemoteEvent> eventQ;
    private final List<EventProducerManager> eventProducerManagers = new ArrayList<EventProducerManager>();
    private final ExecutorService execService = Executors.newCachedThreadPool();

    public void initialize(final EventCollectorContext context) throws Exception {
        if(context==null)
            throw new IllegalArgumentException("context must not be null");
        this.eventQ = context.getEventQueue();
        ServiceDiscoveryManager sdm = new ServiceDiscoveryManager(context.getDiscoveryManager(),
                                                                  new LeaseRenewalManager(context.getConfiguration()),
                                                                  context.getConfiguration());
        for(EventDescriptor eventDescriptor : context.getEventDescriptors()) {
            ServiceTemplate template = new ServiceTemplate(null, null, new Entry[]{eventDescriptor});
            LookupCache lCache = sdm.createLookupCache(template, null,  null);
            EventProducerManager eventProducerManager = new EventProducerManager(eventDescriptor, this, lCache);
            lCache.addListener(eventProducerManager);
            eventProducerManagers.add(eventProducerManager);
        }

    }

    public void terminate() {
        for(EventProducerManager eventProducerManager : eventProducerManagers) {
            eventProducerManager.terminate();
        }
    }

    public void historyNotification(final RegisteredNotification registeredNotification) {
        if(registeredNotification==null)
            throw new IllegalArgumentException("The RegisteredNotification must not be null");
        execService.submit(new EventHistoryNotifier(registeredNotification));
    }

    public void notify(RemoteServiceEvent event) {
        if(logger.isDebugEnabled())
            logger.debug(event.toString());
        eventQ.offer(event);
        postNotify(event);
    }

    public abstract void postNotify(RemoteServiceEvent event);

    protected ExecutorService getExecutorService() {
        return execService;
    }

    /**
     * The EventProducerManager responds to serviceAdded transitions for
     * EventProducer instances which match the EventDescriptor
     */
    class EventProducerManager extends ServiceDiscoveryAdapter {
        final LookupCache lookupCache;
        BasicEventConsumer eventConsumer;
        final EventDescriptor eventDescriptor;
        final RemoteServiceEventListener eventListener;

        EventProducerManager(final EventDescriptor eventDescriptor,
                             final RemoteServiceEventListener eventListener,
                             final LookupCache lookupCache) throws Exception {
            this.lookupCache = lookupCache;
            this.eventDescriptor = eventDescriptor;
            this.eventListener = eventListener;
        }

        /**
         * An EventProducer has been added
         */
        public void serviceAdded(final ServiceDiscoveryEvent sdEvent) {
            ServiceItem item = sdEvent.getPostEventServiceItem();
            try {
                if(item != null && item.service != null) {
                    if(logger.isInfoEnabled()) {
                        String name = item.service.getClass().getName();
                        if(logger.isDebugEnabled()) {
                            logger.debug(String.format("EventProducer discovered %s for EventDescriptor %s",
                                                      name, eventDescriptor.toString()));
                        }
                    }
                    if(eventConsumer==null) {
                        final EventDescriptor eventDescriptorToUse;
                        if(eventDescriptor.eventID==null) {
                            eventDescriptorToUse = getEventDescriptor(item.attributeSets, eventDescriptor);
                        } else {
                            eventDescriptorToUse = eventDescriptor;
                        }
                        eventConsumer = new BasicEventConsumer(eventDescriptorToUse, eventListener);
                    }
                    eventConsumer.register(item);
                    ServiceFaultListener faultListener = new ServiceFaultListener(item.serviceID,
                                                                                  lookupCache,
                                                                                  eventConsumer);
                    lookupCache.addListener(faultListener);
                } else {
                    logger.warn("Unable to register EventProducer {}", item);
                }
            } catch(Exception e) {
                logger.error("Adding EventProducer", e);
            }
        }

        void terminate() {
            if(eventConsumer!=null)
                eventConsumer.terminate();
        }

        EventDescriptor getEventDescriptor(Entry[] attributes, EventDescriptor toMatch) {
            EventDescriptor matchedDescriptor = null;
            for(Entry entry : attributes) {
                if(entry instanceof EventDescriptor) {
                    if(((EventDescriptor)entry).matches(toMatch)) {
                        matchedDescriptor = (EventDescriptor)entry;
                        break;
                    }
                }
            }
            return matchedDescriptor;
        }
    }

    /**
     * Manage service failure notifications
     */
    class ServiceFaultListener extends ServiceDiscoveryAdapter {
        final ServiceID serviceID;
        final LookupCache lookupCache;
        final BasicEventConsumer eventConsumer;

        ServiceFaultListener(final ServiceID serviceID, LookupCache lookupCache, final BasicEventConsumer eventConsumer) {
            this.serviceID = serviceID;
            this.lookupCache = lookupCache;
            this.eventConsumer = eventConsumer;
        }

        /**
         * An EventProducer has been removed
         */
        public void serviceRemoved(final ServiceDiscoveryEvent sdEvent) {
            ServiceItem item = sdEvent.getPreEventServiceItem();
            if(item.service != null) {
                if(item.serviceID.equals(serviceID)) {
                    if(logger.isTraceEnabled()) {
                        String name = item.service.getClass().getName();
                        logger.trace("EventProducer removed {}", name);
                    }
                    terminate();
                }
            } else {
                logger.error("Unable to deregister EventProducer {}, unknown service", item);
            }
        }

        /**
         * Stop listening and remove from local tables
         */
        void terminate() {
            lookupCache.removeListener(this);
            eventConsumer.deregister(serviceID);
        }
    }

    /**
     * This class will read the history and perform the notification to the newly registered listener
     */
    class EventHistoryNotifier implements Runnable {
        final RegisteredNotification registeredNotification;

        EventHistoryNotifier(final RegisteredNotification registeredNotification) {
            this.registeredNotification = registeredNotification;
        }

        public void run() {
            try {
                registeredNotification.setHistoryUpdating(true);
                for(RemoteEvent event : getEvents(registeredNotification.getEventIndex())) {
                    if(!doNotify(event)) {
                        break;
                    }
                }
            } finally {
                registeredNotification.setHistoryUpdating(false);
                for(RemoteEvent event : registeredNotification.getAndClearMissedEvents()) {
                    if(!doNotify(event)) {
                        break;
                    }
                }
            }
        }

        private boolean doNotify(RemoteEvent event) {
            boolean success = false;
            try {
                if(!registeredNotification.isUnknown(event))
                    registeredNotification.getEventListener().notify(event);
                success = true;
            } catch (UnknownEventException e) {
                logger.warn("UnknownEventException return from listener", e);
                registeredNotification.addUnknown(event);
            } catch (RemoteException e) {
                logger.warn("RemoteException return from listener", e);
                if(!ThrowableUtil.isRetryable(e)) {
                    logger.warn(String.format("Unrecoverable exception from %s", registeredNotification));
                }
            }
            return success;
        }
    }
}
TOP

Related Classes of org.rioproject.eventcollector.service.AbstractEventManager$ServiceFaultListener

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.