Package com.sun.enterprise.ee.server.group.core

Source Code of com.sun.enterprise.ee.server.group.core.ServerMessageRuntime

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package com.sun.enterprise.ee.server.group.core;

import com.sun.enterprise.ee.server.group.Message.Route;
import com.sun.enterprise.ee.server.group.MessageAggregator;
import com.sun.enterprise.server.ApplicationServer;
import com.sun.enterprise.server.ServerContext;
import com.sun.enterprise.config.ConfigException;
import com.sun.enterprise.config.serverbeans.ClusterHelper;
import com.sun.enterprise.config.serverbeans.Server;
import com.sun.enterprise.config.serverbeans.ServerHelper;

import com.sun.enterprise.ee.cms.core.GroupManagementService;
import com.sun.enterprise.ee.cms.core.GMSFactory;
import com.sun.enterprise.ee.cms.impl.client.JoinNotificationActionFactoryImpl;
import com.sun.enterprise.ee.server.group.Barrier;
import com.sun.enterprise.ee.server.group.Message;
import com.sun.enterprise.ee.server.group.MessageFactory;
import com.sun.enterprise.ee.server.group.MessageReceiver;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;


/**
* Basic messaging runtime that can be used for sending messages and aggregating
* the responses.
*
* A subsystem need to create the ServerMessageRuntime by calling
* ServerMessageRuntime.create(). It can then use the initiateMessaging method
* to setup the messaging. The ServerMessageRuntime will use CallBack to inform
* the subsystem about the status of the messaging.
*
* FIX ME: Some methods doesnt need to be public....
*
* @author Binod.
*/
public class ServerMessageRuntime {
   
   
    private GroupManagementService gms = null;
    private String thisInstance = null;
    private boolean active = false;
    private String componentName = null;
    private MessageReceiver msgReceiver;
    private Logger __logger = null;
   
    private Map<Message.Route, Map<String, MessageAggregator>> routeMaps
    = new HashMap();
    private String presetElectedInstance;
    private Elector elector;
   
    /**
     * Create a ServerMessageRuntime with a component name and Logger.
     *
     * @param componentName
     * @param logger
     */
    private ServerMessageRuntime(String componentName, Logger logger){
        assert logger != null;
        this.__logger = logger;
        init(componentName);       
    }
   
    /**
     * Static method to create a ServerMessageRuntime. The subsystem that
     * creates the ServerMessageRuntime would usually keep it as a singleton.
     *
     * @param name
     * @param logger
     * @return an instance of ServerMessageRuntime.
     */
    public static ServerMessageRuntime create(String name, Logger logger) {
        return new ServerMessageRuntime(name, logger);
    }

    /**
     * Appserver user can use
     * org.jvnet.glassfish.messagegroup.<componentname>.ElectedInstance property
     * to statically select the instance for notification.
     * 
     * @return Statically selected instance name. Null, if it is not set by
     * the administrator.
     */
    private String getPresetElectedInstance() {
        return this.presetElectedInstance;
    }
   
    /**
     * Initializes the ServerMessageRuntime.
     *
     * @param componentName
     */
    private void init(String componentName) {
       
        this.componentName = componentName;
        ServerContext ctx = ApplicationServer.getServerContext();
        thisInstance = ctx.getInstanceName();
        boolean clustered = false;
        this.presetElectedInstance = System.getProperty
        ("org.glassfish.messagegroup."+componentName+".ElectedInstance");
               

        try {
            clustered = ServerHelper.isServerClustered
            (ctx.getConfigContext(), thisInstance);
        }catch (ConfigException ce) {
            this.__logger.log(Level.SEVERE, ce.getMessage(), ce);           
        }
       
        // If the instance is not clustered, do nothing.... Subsystem that use
        // the ServerMessageRuntime does not need to worry about that.
        if (clustered == false) {
            this.active = false;
            return;
        }       
       
        // Add all the cluster instances to a Set.
        String clusterName = null;
        Set servers = new HashSet();
        try {           
                       
            clusterName = ClusterHelper.getClusterForInstance
            (ctx.getConfigContext(), thisInstance).getName();
           
            Server[] serversArray = (Server[]) ServerHelper.getServersInCluster
            (ctx.getConfigContext(), clusterName);      
           
           
            for (Server server: serversArray) {
                servers.add(server.getName());
            }
           
        } catch (ConfigException ce) {
            __logger.log(Level.SEVERE, ce.getMessage(), ce);
        }
       
        // If GMS is not enabled, do nothing.
        if(!GMSFactory.isGMSEnabled(clusterName)) {
            __logger.log(Level.INFO,
            "GMS is not enabled, ServerMessageRuntime will not proceed for "+
             this.componentName);
            this.active = false;
            return
        }
       
        // Setup a basic data structure table for all routes available.
        // Each route will have its own datastructure for separate house keeping.
        for (Message.Route route: Message.Route.values()) {
            routeMaps.put(route, new ConcurrentHashMap());
        }
       
        try {
            this.gms = GMSFactory.getGMSModule(clusterName);           
            this.msgReceiver =
            new MessageReceiver(this.componentName, thisInstance, this);
           
            JoinCallBackImpl jcb =
            new JoinCallBackImpl(this.gms, servers, __logger);
           
            this.gms.addActionFactory(msgReceiver,this.componentName);
            JoinNotificationActionFactoryImpl jna =
            new JoinNotificationActionFactoryImpl(jcb);
            if (__logger.isLoggable(Level.FINE)) {
                __logger.fine(clusterName +
                " - Added Message Receiver :" + this.componentName);   
            }
            this.gms.addActionFactory(jna);           
           
            // Now lets wait for every instance to join the cluster;
            jcb.waitForEveryone();
            this.gms.removeActionFactory(jna);
           
            __logger.fine("Message Runtime is Initialized");
        } catch (Exception e) {
            __logger.log(Level.SEVERE,e.getMessage(),e);
            this.active = false;
        }
       
        this.active = true;
    }
   
   
    public Logger getLogger() {
        return this.__logger;
    }
   
    /**
     * Return the elected instance. If the pre-selected instance is
     * present, then that is given preference.
     *
     * @return
     */
    public String getElectedInstance() {
       
        String electedInstance = getPresetElectedInstance();
        if (electedInstance == null) {                       
            __logger.finer("Elected Instance is not preset");           
            electedInstance = getElector().getElectedInstance();
        }
       
        if (__logger.isLoggable(Level.FINER)) {
            __logger.finer("Selected the elected instance " + electedInstance);
        }
        return electedInstance;
    }
   
    /**
     * Return the elector instance.
     * @return
     */
    public Elector getElector() {
        if (this.elector == null) {
            this.elector = new ElectorImpl(gms,this);
        }
        return this.elector;       
    }
   
    /**
     * A subsystem can set its own elector implementation.
     *
     * @param el
     */
    public void setElector(Elector el) {
        this.elector = el;
    }
   
    /**
     * Check whether the running instance is the elected instance or not.
     * @return
     */
    public boolean electedSelf() {
        return getElectedInstance().equalsIgnoreCase(thisInstance);
    }
   
    /**
     * Return the Message aggregator for a particular route/key.
     */
    public MessageAggregator getMessageAggregator
            (String key, Message.Route route) {
        synchronized (this) {
            Map<String, MessageAggregator> map =
            this.routeMaps.get(route);
            if (map.containsKey(key) == false) {
                map.put(key, createMA(key, route));
            }
            return map.get(key);
        }
    }
   
    /**
     * Creates a MessageAggregator instance.
     */
    private MessageAggregator createMA(String key, Route route) {
        MessageAggregator ma = new MessageAggregator(key, getServers(route), this);
        ma.setRoute(route);       
        return ma;
    }
   
    /**
     * Returns an existing MA instance or creates a new one.
     */
    private MessageAggregator obtainMA(String key, Route route) {
        MessageAggregator mr = null;
       
        synchronized (this) {
            Map<String, MessageAggregator> aggregatorMap =
            routeMaps.get(route);           
            if (aggregatorMap.containsKey(key) == false) {
                mr = createMA(key, route);                           
                aggregatorMap.put(key, mr);                           
            } else {
                mr = aggregatorMap.get(key);
            }
        }
       
        return mr;
         
    }
   
    /**
     * When messaging for a particluar route/key is completed,
     * remove it from the house keeping.
     */
    public void release(String key, Route route) {
        synchronized (this) {
            Map<String, MessageAggregator> map =
            this.routeMaps.get(route);
            if (map.containsKey(key)) {
                map.remove(key);
            }
        }      
    }

    public void purge(String key) {
        for (Map<String, MessageAggregator> m : routeMaps.values()) {
             if (m.containsKey(key)) {
                 m.remove(key);
             }
        }
    }
   
    /**
     * Return the appropriate list of servers from where messages are
     * expected. For an ALLTOONE route, the messages are expected from
     * all instances except the current one.
     *
     * For ONETOALL messages are expeted only from the elected instance.
     */
    private List getServers(Message.Route route) {  
        List<String> al = new ArrayList();
        switch (route) {
            case ALLTOONE :
                List<String> members =
                this.gms.getGroupHandle().getCurrentCoreMembers();
                   
                for (String member : members) {
                    if (! member.equals(getElectedInstance()))
                       al.add(member);
                    }
                   
                return al;
            case ONETOALL :           
                al.add(this.getElectedInstance());
                return al;
        }              
        return null;
    }
   
    /**
     * Used by the subsystems. This method waits until the messaging is
     * over for a particular route/key. "key" in case of deployment is
     * the application name.
     *
     * The CallBack interface passed in by the subsystem will be used to
     * send notifications about the messaging status.
     */
    public void initiateMessagingAndWait(String key,
    Message.Route route, CallBack cb) {              
       
        Barrier b = initiateMessaging(key, route, cb);
        if (b != null) {
            b.start();        
        }       
       
    }
   
    /**
     * Used by the subsystems. This method waits until the messaging is
     * over for a particular route/key. "key" in case of deployment is
     * the application name.
     *
     * The CallBack interface passed in by the subsystem will be used to
     * send notifications about the messaging status.
     *
     * Barrier is returned to the subsystem so that, it can wait for the
     * completion on a different thread.
     */
    public Barrier initiateMessaging(String key,
    Message.Route route, CallBack cb) {
       
        // If runtime is not initialized, for eg: in developer profile, return
        // null;
        if (!active) return null;
       
        /**
         * If the current instance is the one elected for sending notifications
         * then for ONETOALL route, it will just send messages to all others
         * in the cluster. For ALLTOONE, it will wait for message from others
         * in the cluster. So, barrier will be raised.
         *
         * If the current instance is not the elected instance, for ONETOALL, it
         * will wait for the message from other instances with the same
         * route/key. For ALLTOONE, it will send a message to the elected
         * instance and proceed.
         */
        if (electedSelf()) {   
            if (__logger.isLoggable(Level.FINE)) {
                __logger.log(Level.FINE, "This instance is elected for sending"+
               " messages");
            }
            switch (route) {
                case ONETOALL :
                    Message mesg = MessageFactory.createMessage(route);
                    mesg.setAggregationKey(key);
                    try {
                        cb.messagingCompleted();
                        if (__logger.isLoggable(Level.FINE)) {
                           __logger.fine("Sending ...." + mesg.toString());
                        }
                        gms.getGroupHandle().
                        sendMessage(this.componentName, mesg.toBytes());
                    } catch (Exception e) {
                        e.printStackTrace();
                        // FIX ME.
                    }
                    break;
                case NONE :
                    // No ROUTE lets timeout...
                    if (cb != null)
                        cb.messagingTimedOut();
                    break;
                case ALLTOONE :                                            
                    MessageAggregator mr = obtainMA(key, route)
                    mr.setCallBack(cb);
                    return mr.getBarrier();               
            }
        } else {           
            switch (route) {
                case ALLTOONE :
                    Message mesg = MessageFactory.createMessage(route);
                    mesg.setAggregationKey(key);
                    try {
                        if (__logger.isLoggable(Level.FINE)) {
                            __logger.fine("Sending ALLTOONE ...."
                            + mesg.toString() + "To " + getElectedInstance());
                        }
                        //gms.getGroupHandle().sendMessage
                        //(this.componentName, getElectedInstance(), mesg.toBytes());
                        gms.getGroupHandle().sendMessage
                        (this.componentName, mesg.toBytes());
                    } catch (Exception e) {
                        e.printStackTrace();
                        // FIX ME.
                    }
                    break;
                case ONETOALL : 
                    MessageAggregator mr = obtainMA(key, route);                     
                    return mr.getBarrier();                   
            }
           
        }
       
        return null;
    }
   
}
TOP

Related Classes of com.sun.enterprise.ee.server.group.core.ServerMessageRuntime

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.