esg.node.core.AbstractDataNodeComponent.java Source code

Java tutorial

Introduction

Here is the source code for esg.node.core.AbstractDataNodeComponent.java

Source

/***************************************************************************
 *                                                                          *
 *  Organization: Lawrence Livermore National Lab (LLNL)                    *
 *   Directorate: Computation                                               *
 *    Department: Computing Applications and Research                       *
 *      Division: S&T Global Security                                       *
 *        Matrix: Atmospheric, Earth and Energy Division                    *
 *       Program: PCMDI                                                     *
 *       Project: Earth Systems Grid (ESG) Data Node Software Stack         *
 *  First Author: Gavin M. Bell (gavin@llnl.gov)                            *
 *                                                                          *
 ****************************************************************************
 *                                                                          *
 *   Copyright (c) 2009, Lawrence Livermore National Security, LLC.         *
 *   Produced at the Lawrence Livermore National Laboratory                 *
 *   Written by: Gavin M. Bell (gavin@llnl.gov)                             *
 *   LLNL-CODE-420962                                                       *
 *                                                                          *
 *   All rights reserved. This file is part of the:                         *
 *   Earth System Grid (ESG) Data Node Software Stack, Version 1.0          *
 *                                                                          *
 *   For details, see http://esgf.org/esg-node/                    *
 *   Please also read this link                                             *
 *    http://esgf.org/LICENSE                                      *
 *                                                                          *
 *   * Redistribution and use in source and binary forms, with or           *
 *   without modification, are permitted provided that the following        *
 *   conditions are met:                                                    *
 *                                                                          *
 *   * Redistributions of source code must retain the above copyright       *
 *   notice, this list of conditions and the disclaimer below.              *
 *                                                                          *
 *   * Redistributions in binary form must reproduce the above copyright    *
 *   notice, this list of conditions and the disclaimer (as noted below)    *
 *   in the documentation and/or other materials provided with the          *
 *   distribution.                                                          *
 *                                                                          *
 *   Neither the name of the LLNS/LLNL nor the names of its contributors    *
 *   may be used to endorse or promote products derived from this           *
 *   software without specific prior written permission.                    *
 *                                                                          *
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS    *
 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT      *
 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS      *
 *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LAWRENCE    *
 *   LIVERMORE NATIONAL SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR     *
 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,           *
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT       *
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF       *
 *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    *
 *   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,     *
 *   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT     *
 *   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF     *
 *   SUCH DAMAGE.                                                           *
 *                                                                          *
 ***************************************************************************/

/**
   Description:
    
**/
package esg.node.core;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.impl.*;

import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;

public abstract class AbstractDataNodeComponent implements DataNodeComponent {

    private static Log log = LogFactory.getLog(AbstractDataNodeComponent.class);

    private String myName = null;
    private DataNodeManager dataNodeManager = null;
    private ESGQueue eventQueue = null;

    //Expose this list to available subclasses...
    //so that they too may be able to manage event listeners
    protected List<ESGListener> esgListeners = null;
    protected Map<String, ESGQueueListener> esgQueueListenersMap = null;

    public AbstractDataNodeComponent(String name) {
        this.myName = name;
        this.esgListeners = Collections.synchronizedList(new ArrayList<ESGListener>());
        this.esgQueueListenersMap = Collections.synchronizedMap(new HashMap<String, ESGQueueListener>());
        this.eventQueue = new ESGQueue(this);
    }

    public AbstractDataNodeComponent() {
        this(DataNodeComponent.ANONYMOUS);
    }

    public void start() {
        log.info("Starting... " + this.getClass().getName());
        init();
    }

    public abstract void init();

    protected final void setMyName(String myName) {
        this.myName = myName;
    }

    protected final void setDataNodeManager(DataNodeManager dataNodeManager) {
        this.dataNodeManager = dataNodeManager;
    }

    public String getName() {
        return myName;
    }

    public final DataNodeManager getDataNodeManager() {
        return dataNodeManager;
    }

    //To be nice this should be called upon destruction
    //(TODO: Make this a phantom reference in the manager)
    public void stop() {
        log.info("Stopping... " + this.getClass().getName());
        unregister();
    }

    public void unregister() {
        if (dataNodeManager == null)
            return;
        dataNodeManager.removeComponent(this);
        dataNodeManager = null;

        //TODO: Add an abstract method or make one of the two that we
        //have abstract so that the component subclass can be called
        //to stop it's life cycle appropriately. (see:
        //AbstractDataNodeManager.removeComponent()).
    }

    //*******************************************    
    //-------------------------------------------
    //Queue Listener Query methods...
    //-------------------------------------------
    public int numOfESGListeners() {
        return esgListeners.size();
    }

    public String[] getESGListenerNames() {
        String[] esgListenerNames = new String[esgListeners.size()];
        int index = 0;
        for (String esgListenerName : esgQueueListenersMap.keySet()) {
            esgListenerNames[index++] = esgListenerName;
        }
        return esgListenerNames;
    }

    //-------------------------------------------
    //Subscribe/Unsubscribe ESGListeners ("system" events)
    //-------------------------------------------
    public void addESGListener(ESGListener listener) {
        if (listener == null)
            return;
        log.trace("Adding Listener: " + listener);
        esgListeners.add(listener);
    }

    public void removeESGListener(ESGListener listener) {
        log.trace("Removing Listener: " + listener);
        esgListeners.remove(listener);
    }

    public void removeAllESGListeners() {
        log.trace("Removing ALL (" + esgListeners.size() + ") ESG Listeners from " + this.getName());
        esgListeners.clear();
    }

    //--------------------------------------------
    //Event dispatching to all registered ESGListeners
    //calling their handleESGEvent method
    //--------------------------------------------
    protected void fireESGEvent(ESGEvent esgEvent) {
        log.trace("Firing Event: " + esgEvent);
        for (ESGListener listener : esgListeners) {
            listener.handleESGEvent(esgEvent);
        }
    }

    //-------------------------------------------
    //ESGListener Interface Implementation...
    //-------------------------------------------
    public void handleESGEvent(ESGEvent event) {
        //TODO:
        //Just stubbed for now...
        log.trace("(no-op) handling event -[" + myName + "]:[" + this.getClass().getName() + "]: Got An Event!!!!: "
                + event);
    }
    //*******************************************

    //*******************************************
    //-------------------------------------------
    //Queue Listener Query methods...
    //-------------------------------------------
    public int numOfESGQueueListeners() {
        return esgQueueListenersMap.size();
    }

    public String[] getESGQueueListenerNames() {
        String[] esgQueueListenerNames = new String[esgQueueListenersMap.size()];
        int index = 0;
        for (String queuelistenerName : esgQueueListenersMap.keySet()) {
            esgQueueListenerNames[index++] = queuelistenerName;
        }
        return esgQueueListenerNames;
    }

    //-------------------------------------------
    //Subscribe/Unsubscribe ESG Queue Listeners ("application" events)
    //-------------------------------------------
    public void addESGQueueListener(ESGQueueListener listener) {
        if (listener == null)
            return;
        log.trace("Adding Queue Listener: " + listener + " to " + this.getName());
        esgQueueListenersMap.put(listener.getName(), listener);
    }

    public void removeESGQueueListener(ESGQueueListener listener) {
        log.trace("Removing Listener: " + listener + " from " + this.getName());
        esgQueueListenersMap.remove(listener.getName());
    }

    public void removeESGQueueListener(String listenerName) {
        log.trace("Removing Queue Listener named: " + listenerName + " from " + this.getName());
        esgQueueListenersMap.remove(listenerName);
    }

    public void removeAllESGQueueListeners() {
        log.trace("Removing ALL (" + esgQueueListenersMap.size() + ": [" + getESGQueueListenerNames()
                + "]) Queue Listeners from " + this.getName());
        esgQueueListenersMap.clear();
    }

    //--------------------------------------------
    //Event dispatching to all registered ESGQueueListeners
    //calling their Queue's handleEvent method
    //(The queued version of the "fire" method)
    //--------------------------------------------
    protected void enqueueESGEvent(ESGEvent esgEvent) {
        log.trace("Enqueuing Event (to all listeners): " + esgEvent);
        for (ESGQueueListener listener : esgQueueListenersMap.values()) {
            log.trace("--to--> " + listener.getName());
            listener.getESGEventQueue().enqueueEvent(esgEvent);
        }
    }

    protected void enqueueESGEvent(String destinationListenerName, ESGEvent esgEvent) {
        log.trace("Enqueuing Event: " + esgEvent + " --to--> " + destinationListenerName);
        ESGQueueListener nextHop = esgQueueListenersMap.get(destinationListenerName);
        if (nextHop != null) {
            nextHop.getESGEventQueue().enqueueEvent(esgEvent);
        } else {
            log.warn("Sorry " + myName + " ,there isn't another component for you to dispatch to!");
            log.warn("      Dropping event, " + esgEvent + " on the floor :-(");
        }
    }

    //-------------------------------------------
    //ESGQueueListener Interface Implementation... (Called by my ESGQueue)
    //-------------------------------------------
    public boolean handleESGQueuedEvents(List<ESGEvent> events) {
        boolean ret = true;
        log.trace("(no-op) handling enqueued events [" + myName + "]:[" + this.getClass().getName()
                + "]: Got Batch of [" + events.size() + "] QueuedEvents! ");
        for (ESGEvent event : events) {
            ret &= handleESGQueuedEvent(event);
        }
        return ret;
    }

    public boolean handleESGQueuedEvent(ESGEvent event) {
        log.trace("(no-op) handling enqueued event [" + myName + "]:[" + this.getClass().getName()
                + "]: Got A QueuedEvent!!!!: " + event);
        //TODO: Upon handling of this event pass it on to the next event in the chain.
        //Call enqueueESGEvent(<name_of_next_component>, event);
        enqueueESGEvent(event);
        return false;
    }

    public ESGQueue getESGEventQueue() {
        return eventQueue;
    }
    //*******************************************

    //We want to do what we can not to leave references laying around
    //in the data node manager.  Unregistering will explicitly take us
    //out of the data node manager.  (TODO: look into making the data
    //node manager use phatom references to components).
    //protected void finalize() throws Throwable { super.finalize(); unregister(); }

}