org.openspaces.core.gateway.GSCForkHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.openspaces.core.gateway.GSCForkHandler.java

Source

/*******************************************************************************
 *
 * Copyright (c) 2012 GigaSpaces Technologies Ltd. All rights reserved
 *
 * 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.openspaces.core.gateway;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openspaces.admin.gsa.GridServiceAgent;
import org.openspaces.admin.gsa.GridServiceContainerOptions;
import org.openspaces.admin.gsc.GridServiceContainer;
import org.openspaces.admin.pu.ProcessingUnitInstance;
import org.springframework.util.StringUtils;

/**
 * A class responsible for forking a new GSC for the WAN Gateway, and relocating
 * this PU instance (the gateway) to the new container. Forking is performed
 * with the admin api, or by calling the GSC script directly.
 *
 * @author barakme
 * @author eitany
 * @since 8.0.3
 */
public class GSCForkHandler {

    private static final int ADMIN_GSC_STARTUP_TIMEOUT_SECS = 600;

    protected final Log logger = LogFactory.getLog(GSCForkHandler.class);

    private final ProcessingUnitInstance pui;
    private final int lrmiPort;
    private final int discoveryPort;

    private static final String LRMI_PORT_SYSTEM_PROPERTY = "com.gs.transport_protocol.lrmi.bind-port";
    private static final String LRMI_PORT_PROPERTY_TEMPLATE = "-D" + LRMI_PORT_SYSTEM_PROPERTY + "=<LRMI_PORT>";

    private static final String DISCOVERY_PORT_SYSTEM_PROPERTY = "com.sun.jini.reggie.initialUnicastDiscoveryPort";
    private static final String DISCOVERY_PORT_PROPERTY_TEMPLATE = "-D" + DISCOVERY_PORT_SYSTEM_PROPERTY
            + "=<DISCOVERY_PORT>";

    public static final String AGENT_EXT_JAVA_OPTIONS = LRMI_PORT_PROPERTY_TEMPLATE + " "
            + DISCOVERY_PORT_PROPERTY_TEMPLATE;

    private final boolean startEmbeddedLus;
    private final String customJvmProperties;

    /****
     *
     * Constructor.
     * @param lrmiPort the target GSC port.
     * @param discoveryPort the target discovery port.
     * @param startEmbeddedLus
     * @param pui the PU instance object of the current PU.
     * @param customJvmProperties
     */
    public GSCForkHandler(int lrmiPort, int discoveryPort, boolean startEmbeddedLus, ProcessingUnitInstance pui,
            String customJvmProperties) {

        this.lrmiPort = lrmiPort;
        this.startEmbeddedLus = startEmbeddedLus;
        this.pui = pui;
        this.discoveryPort = discoveryPort;
        this.customJvmProperties = customJvmProperties;
    }

    private String createDiscoveryPortProperty(final int discoveryPort) {
        return DISCOVERY_PORT_PROPERTY_TEMPLATE.replace("<DISCOVERY_PORT>", Integer.toString(discoveryPort));

    }

    private String createLrmiPortProperty(final int gscPort) {
        return LRMI_PORT_PROPERTY_TEMPLATE.replace("<LRMI_PORT>", Integer.toString(gscPort));

    }

    private String[] createGSCExtraCommandLineArguments() {
        List<String> arguments = new LinkedList<String>();
        if (lrmiPort != 0)
            arguments.add(createLrmiPortProperty(lrmiPort));
        if (startEmbeddedLus)
            arguments.add(createDiscoveryPortProperty(discoveryPort));
        if (StringUtils.hasLength(customJvmProperties))
            arguments.addAll(Arrays.asList(customJvmProperties.split(" ")));
        return arguments.toArray(new String[arguments.size()]);
    }

    /***********
     * This is the main entry point of this class. This method creates a new GSC
     * and moves this PUI to the new GSC.
     */
    public void movePuToAlternativeGSC() {
        logger.info("Locating GSC which meets communication/discovery ports requirement");
        GridServiceContainer gsc = locateExistingGSCWithPorts();
        if (gsc == null) {
            logger.info("Suitable GSC not found - attempting to create a new GSC");
            if (!GatewayUtils.checkPortAvailable(lrmiPort)) {
                String exceptionMessage = "The required communication port for the new GSC(" + lrmiPort
                        + ") is not available!";
                logger.error(exceptionMessage);
                throw new IllegalArgumentException(exceptionMessage);
            }
            if (startEmbeddedLus && !GatewayUtils.checkPortAvailable(discoveryPort)) {
                String exceptionMessage = "The required discovery port for the new GSC(" + discoveryPort
                        + ") is not available!";
                logger.error(exceptionMessage);
                throw new IllegalArgumentException(exceptionMessage);
            }

            GridServiceAgent gsa = null;
            logger.info("Looking up GSA on local machine");
            gsa = findLocalGSA();
            if (gsa == null) {
                logger.error("Could not find local GSA. Cannot start alternative GSC");
                throw new IllegalStateException("Could not find local GSA. Cannot start alternative GSC");
            }

            logger.info("Found local GSA - starting new GSC");
            gsc = createGSCWithGsa(gsa);
            logger.info("Created new GSC: " + gsc.getUid() + ", relocating this instance into it");
        } else {
            logger.info("Found existing GSC: " + gsc.getUid()
                    + " with matching ports, relocating this instance into it");
        }

        logger.info("Relocating " + pui.getProcessingUnitInstanceName() + " to GSC uid=" + gsc.getUid()
                + " machine=" + gsc.getMachine().getHostAddress() + " pid="
                + gsc.getVirtualMachine().getDetails().getPid());
        pui.relocate(gsc);

    }

    private GridServiceContainer locateExistingGSCWithPorts() {
        for (GridServiceContainer gsc : this.pui.getAdmin().getGridServiceContainers()) {
            int gscPort = gsc.getTransport().getPort();
            if (gscPort == lrmiPort) {
                return gsc;
            }
        }
        return null;
    }

    private GridServiceContainer createGSCWithGsa(final GridServiceAgent gsa) {
        GridServiceContainer gsc;

        // set up the GSC parameters
        final GridServiceContainerOptions gsco = new GridServiceContainerOptions();
        final String[] props = createGSCExtraCommandLineArguments();

        for (final String prop : props) {
            gsco.vmInputArgument(prop);
        }

        logger.info("starting GSC with parameters: " + Arrays.toString(props));

        // start the GSC
        gsc = gsa.startGridServiceAndWait(gsco, ADMIN_GSC_STARTUP_TIMEOUT_SECS, TimeUnit.SECONDS);

        if (gsc == null) {
            throw new IllegalStateException("Failed to create new GSC for gateway");
        }
        return gsc;
    }

    private GridServiceAgent findLocalGSA() {

        final GridServiceContainer gsc = this.pui.getGridServiceContainer();
        if (gsc == null) {
            logger.error("Error - could not find the GSC that this PUI belongs to");
            return null;
        }

        final GridServiceAgent gsa = gsc.getGridServiceAgent();
        return gsa;

    }
}