Package org.jboss.dashboard.cluster

Source Code of org.jboss.dashboard.cluster.ClusterNodesManager

/**
* Copyright (C) 2012 JBoss Inc
*
* 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.jboss.dashboard.cluster;

import org.hibernate.Query;
import org.hibernate.Session;
import org.jboss.dashboard.annotation.Priority;
import org.jboss.dashboard.annotation.Startable;
import org.jboss.dashboard.database.hibernate.HibernateTxFragment;

import javax.enterprise.context.ApplicationScoped;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;

/**
* A platform component that manages the nodes connected to the cluster, if any.
*
* NOTE: BZ-1014612
*/
@ApplicationScoped
public class ClusterNodesManager implements Startable {
    public static transient org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ClusterNodesManager.class.getName());

    /** The id for this node. **/
    private Long currentNodeId;

    /** The IP address for the node. **/
    private String currentNodeIpAddress;

    /**
     * Use highest priority to register the nodes and their statuses as quick as possible on startup.
     *
     * It must has lower priority than startable <code>HibernateInitializer</code> in order to have a valid Hibernate session.
     * @return An urgent priority.
     */
    public Priority getPriority() {
        return Priority.HIGH;
    }

    /**
     * Register the node into the table.
     *
     * @throws Exception Error registering node.
     */
    @Override
    public void start() throws Exception {
        // Obtain node IP address from system.
        currentNodeIpAddress = getIPAddress();

        log.info("Registering cluster node with ip address " + currentNodeIpAddress);

        final ClusterNode[] result = new ClusterNode[1];
        new HibernateTxFragment(true, true) {
            protected void txFragment(Session session) throws Exception {

                // Check if the node is already regisitered from a previous execution.
                ClusterNode node = getNodeByIpAddress(currentNodeIpAddress);

                if (node == null) {
                    // Create the cluster node instance.
                    node = new ClusterNode();
                }
                node.setNodeAddress(currentNodeIpAddress);
                node.setStartupTime(new Date());
                node.setNodeStatus(ClusterNode.ClusterNodeStatus.REGISTERED.name());
                session.saveOrUpdate(node);

                session.flush();

                result[0] = node;
            }

            @Override
            protected void afterRollback() throws Throwable {
                super.afterRollback();
                log.error("This cluster node cannot be registered.");
            }

        }.execute();

        if (result[0] != null) this.currentNodeId = result[0].getId();

        log.info("Successfully registered cluster node with ip address " + currentNodeIpAddress + " and identifier " + this.currentNodeId);
    }

    /**
     * Deregister the node from the table.
     *
     * @throws Exception Error deregistering node.
     */
    public void deregister(final Long nodeId) throws Exception {
        if (nodeId == null) {
            log.error("This cluster node was not previously registered.");
            return;
        }

        log.info("Deregistering cluster node with id " + nodeId);

        new HibernateTxFragment(true, true) {
            protected void txFragment(Session session) throws Exception {
                // Delete the cluster node register.
                Query query = session.createQuery("delete from " + ClusterNode.class.getName() +" cn  where cn.id = :idNode");
                query.setLong("idNode", nodeId);
                query.executeUpdate();

                session.flush();
            }

            @Override
            protected void afterRollback() throws Throwable {
                super.afterRollback();
                log.error("This cluster node cannot be deregistered.");
            }

        }.execute();

        log.info("Successfully deregistered cluster node with id " + nodeId);
    }


    /**
     * Returns a cluster node/s instance for a given status. Several nodes can have same ip address.
     *
     * @param status The status for the node.
     * @return The cluster node/s or <code>null</code> if there is no match.
     * @throws Exception Error searching for a cluster node by status.
     */
    public List<ClusterNode> getNodeByStatus(final ClusterNode.ClusterNodeStatus status) throws  Exception {
        final List<ClusterNode> result = new ArrayList<ClusterNode>();
        if (status != null) {
            new HibernateTxFragment() {
                protected void txFragment(Session session) throws Exception {
                    Query query = session.createQuery("from " + ClusterNode.class.getName() +" cn  where cn.nodeStatus = :nStatus");
                    query.setString("nStatus", status.name());
                    List queryResult = query.list();

                    if (queryResult != null && !queryResult.isEmpty()) {
                        for (Object obj : queryResult) {
                            result.add((ClusterNode) obj);
                        }
                    }
                }
            }.execute();
        }

        return result;
    }

    /**
     * Returns a cluster node instance for a given identifier.
     *
     * @param id The identifier for the node.
     * @return The cluster node or <code>null</code> if there is no match.
     * @throws Exception Error searching for a cluster node by identifier.
     */
    public ClusterNode getNodeById(final Long id) throws  Exception {
        final ClusterNode[] result = new ClusterNode[1];
        if (id != null) {
            new HibernateTxFragment() {
                protected void txFragment(Session session) throws Exception {
                    Query query = session.createQuery("from " + ClusterNode.class.getName() +"  cn  where cn.id = :idToSearch");
                    query.setLong("idToSearch", id);
                    List queryResult = query.list();

                    if (queryResult.size() > 1) log.error("There is more than one cluster node resgistered for identifier " + id + ".!!!");
                    if (!queryResult.isEmpty()) result[0] = (ClusterNode) queryResult.get(0);
                }
            }.execute();
        }

        return result[0];
    }

    /**
     * Returns a cluster node instance for a given IP address.
     *
     * @param ip The ip address for the node.
     * @return The cluster node or <code>null</code> if there is no match.
     * @throws Exception Error searching for a cluster node by ip address.
     */
    public ClusterNode getNodeByIpAddress(final String ip) throws  Exception {
        final ClusterNode[] result = new ClusterNode[1];
        if (ip != null) {
            new HibernateTxFragment() {
                protected void txFragment(Session session) throws Exception {
                    Query query = session.createQuery("from " + ClusterNode.class.getName() +"  cn  where cn.nodeAddress = :ipToSearch");
                    query.setString("ipToSearch", ip);
                    List queryResult = query.list();

                    if (queryResult.size() > 1) log.error("There is more than one cluster node resgistered for IP address: " + ip + ".");
                    if (!queryResult.isEmpty()) result[0] = (ClusterNode) queryResult.get(0);
                }
            }.execute();
        }

        return result[0];
    }

    /**
     * Return the IP address for the default interface.
     *
     * @return The IP address for the default interface.
     * @throws SocketException Error reading socket.
     */
    protected String getIPAddress() throws SocketException{
        String ip = null;
        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
        while (interfaces.hasMoreElements()) {
            NetworkInterface iface = interfaces.nextElement();
            // filters out 127.0.0.1 and inactive interfaces
            if (iface.isLoopback() || !iface.isUp())
                continue;

            Enumeration<InetAddress> addresses = iface.getInetAddresses();
            while(addresses.hasMoreElements()) {
                InetAddress addr = addresses.nextElement();
                ip = addr.getHostAddress();
            }
        }

        return ip;
    }

    /**
     * Sets a status for a node.
     *
     * @param nodeId The node identifier.
     * @param newStatus The new status to set.
     */
    public void setNodeStatus(final Long nodeId, final ClusterNode.ClusterNodeStatus newStatus) throws Exception{
        new HibernateTxFragment() {
            protected void txFragment(Session session) throws Exception {
                ClusterNode node = getNodeById(nodeId);

                if (node == null) {
                    log.error("Cannot set status " + newStatus.name() + " to target node. Node with identifier " + nodeId + " not found.");
                } else {
                    node.setNodeStatus(newStatus.name());
                    session.saveOrUpdate(node);
                    session.flush();
                }
            }
        }.execute();
    }

    /**
     * Check if another node is currently installing initial modules.
     * If no other node is installing initial modules, install the modules and register node status to state: installing_modules.
     * If another node is installing initial modules, skip initial modules installation from this node.
     *
     * IMPORTANT NOTE: Perform the change node status in bbdd in a new transaction.
     *
     * NOTE: BZ-1014612
     *
     * @return If this node should install initial modules.
     */
    public boolean shouldInstallModules() throws Exception {
        final Boolean[] result = new Boolean[1];
        result[0] = true;
        new HibernateTxFragment(true, true) {
            protected void txFragment(Session session) throws Exception {
                List<ClusterNode> installingModulesNodes = getNodeByStatus(ClusterNode.ClusterNodeStatus.INSTALLING_MODULES);
                if (installingModulesNodes != null && !installingModulesNodes.isEmpty()) {
                    if (installingModulesNodes.size() > 1) {
                        log.warn("More than one cluster node status is INSTALLING_MODULES. This situation can be produced due to a failured previous installation.");
                    }
                    ClusterNode node = installingModulesNodes.get(0);

                    if (node.getNodeAddress() != null && node.getNodeAddress().equals(getCurrentNodeIpAddress())) {
                        // BZ-1047123
                        // If the node with status INSTALLING_MODULES is this one, probably the last installation was failed.
                        // So show a warning and re-install modules.
                        result[0] = true;
                    } else {
                        // Other node is installing. This node should NOT be the installer.
                        result[0] = false;
                    }
                } else {
                    // No other node is installing. This node should be the installer.
                    result[0] = true;
                    setCurrentNodeStatus(ClusterNode.ClusterNodeStatus.INSTALLING_MODULES);
                }
            }

        }.execute();

        return result[0];
    }

    /**
     * Sets a status for current node.
     *
     * @param newStatus The new status to set.
     */
    public void setCurrentNodeStatus(ClusterNode.ClusterNodeStatus newStatus) throws Exception {
        setNodeStatus(this.currentNodeId, newStatus);
    }

    public Long getCurrentNodeId() {
        return currentNodeId;
    }

    public String getCurrentNodeIpAddress() {
        return currentNodeIpAddress;
    }
}
TOP

Related Classes of org.jboss.dashboard.cluster.ClusterNodesManager

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.