org.openspaces.grid.gsm.containers.ContainersSlaUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.openspaces.grid.gsm.containers.ContainersSlaUtils.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.grid.gsm.containers;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.commons.logging.Log;
import org.openspaces.admin.Admin;
import org.openspaces.admin.AdminException;
import org.openspaces.admin.GridComponent;
import org.openspaces.admin.gsa.GridServiceAgent;
import org.openspaces.admin.gsc.GridServiceContainer;
import org.openspaces.admin.internal.admin.InternalAdmin;
import org.openspaces.admin.internal.gsa.InternalGridServiceAgent;
import org.openspaces.admin.internal.gsc.InternalGridServiceContainer;
import org.openspaces.admin.internal.pu.elastic.GridServiceContainerConfig;
import org.openspaces.admin.machine.Machine;
import org.openspaces.admin.os.OperatingSystemStatistics;
import org.openspaces.admin.pu.ProcessingUnit;
import org.openspaces.admin.vm.VirtualMachineAware;
import org.openspaces.core.util.MemoryUnit;
import org.openspaces.grid.gsm.machines.MachinesSlaUtils;

public class ContainersSlaUtils {

    static FutureGridServiceContainer startGridServiceContainerAsync(final InternalAdmin admin,
            final InternalGridServiceAgent gsa, final GridServiceContainerConfig config, final Log logger,
            final long duration, final TimeUnit timeUnit) {

        final AtomicReference<Object> ref = new AtomicReference<Object>(null);
        final long startTimestamp = System.currentTimeMillis();
        final long end = startTimestamp + timeUnit.toMillis(duration);

        admin.scheduleAdminOperation(new Runnable() {
            public void run() {
                try {
                    final OperatingSystemStatistics operatingSystemStatistics = gsa.getMachine()
                            .getOperatingSystem().getStatistics();

                    // get total free system memory + cached (without sigar returns -1)
                    long freeBytes = operatingSystemStatistics.getActualFreePhysicalMemorySizeInBytes();
                    if (freeBytes <= 0) {
                        // fallback - no sigar. Provides a pessimistic number since does not take into
                        // account OS cache that can be allocated.
                        freeBytes = operatingSystemStatistics.getFreePhysicalMemorySizeInBytes();
                        if (freeBytes <= 0) {
                            // machine is probably going down.
                            ref.set(new AdminException("Cannot determine machine "
                                    + machineToString(gsa.getMachine()) + " free memory."));
                        }
                    }

                    final long freeInMB = MemoryUnit.MEGABYTES.convert(freeBytes, MemoryUnit.BYTES);
                    if (freeInMB < config.getMaximumJavaHeapSizeInMB()) {
                        ref.set(new AdminException("Machine " + machineToString(gsa.getMachine()) + " free memory "
                                + freeInMB + "MB is not enough to start a container with "
                                + config.getMaximumJavaHeapSizeInMB()
                                + "MB. Free machine memory or increase machine provisioning reservedMemoryPerMachine property."));
                    } else {
                        ref.set(gsa.internalStartGridService(config));
                    }
                } catch (AdminException e) {
                    ref.set(e);
                } catch (Throwable e) {
                    logger.error("Unexpected Exception " + e.getMessage(), e);
                    ref.set(e);
                }
            }
        });

        FutureGridServiceContainer future = new FutureGridServiceContainer() {

            public boolean isTimedOut() {
                return System.currentTimeMillis() > end;
            }

            public ExecutionException getException() {
                Object result = ref.get();
                if (result != null && result instanceof Throwable) {
                    Throwable throwable = (Throwable) result;
                    return new ExecutionException(throwable.getMessage(), throwable);
                }
                return null;
            }

            public GridServiceContainer get() throws ExecutionException, IllegalStateException, TimeoutException {

                Object result = ref.get();

                if (getException() != null) {
                    throw getException();
                }

                GridServiceContainer container = null;
                if (result != null) {
                    int agentId = (Integer) result;
                    container = getGridServiceContainerInternal(agentId);
                    //container could still be null if not discovered
                }

                if (container == null) {
                    if (isTimedOut()) {
                        throw new TimeoutException("Starting a new container took more than "
                                + timeUnit.toSeconds(duration) + " seconds to complete.");
                    }

                    throw new IllegalStateException("Async operation is not done yet.");
                }

                return container;

            }

            public boolean isDone() {
                Object result = ref.get();

                if (System.currentTimeMillis() > end) {
                    return true;
                }

                if (result == null) {
                    return false;
                }

                if (result instanceof Throwable) {
                    return true;
                }

                GridServiceContainer container = getGridServiceContainerInternal((Integer) result);
                if (container != null) {
                    return true;
                }

                return false;
            }

            public GridServiceContainer getGridServiceContainerInternal(int agentId) {
                for (GridServiceContainer container : admin.getGridServiceContainers()) {

                    String agentUid = ((InternalGridServiceContainer) container).getAgentUid();
                    if (agentUid != null && agentUid.equals(gsa.getUid())) {
                        if (agentId == container.getAgentId()) {
                            return container;
                        }
                    }
                }
                return null;
            }

            public GridServiceAgent getGridServiceAgent() {
                return gsa;
            }

            public GridServiceContainerConfig getGridServiceContainerConfig() {
                return config;
            }

            public Date getTimestamp() {
                return new Date(startTimestamp);
            }

            @Override
            public int getAgentId() throws ExecutionException, TimeoutException {
                ExecutionException exception = getException();
                if (exception != null) {
                    throw exception;
                }

                if (isTimedOut() && ref.get() == null) {
                    throw new TimeoutException(
                            "Starting a new container on machine " + gsa.getMachine().getHostAddress()
                                    + " took more than " + timeUnit.toSeconds(duration) + " seconds to complete.");
                }

                if (ref.get() == null) {
                    throw new IllegalStateException("Async operation is not done yet.");
                }

                return (Integer) ref.get();
            }

            public boolean isStarted() {
                return ref.get() != null;
            }
        };

        return future;
    }

    public static Collection<GridServiceContainer> getContainersByZone(Admin admin, String zone) {
        List<GridServiceContainer> containers = new ArrayList<GridServiceContainer>();
        for (GridServiceContainer container : admin.getGridServiceContainers()) {
            if (isContainerMatchesZone(container, zone) && container.getGridServiceAgent() != null) {
                containers.add(container);
            }
        }
        return containers;
    }

    public static List<GridServiceContainer> getContainersByZoneOnAgentUid(Admin admin, String zone,
            String agentUid) {
        List<GridServiceContainer> containers = new ArrayList<GridServiceContainer>();
        for (GridServiceContainer container : admin.getGridServiceContainers()) {
            if (isContainerMatchesZone(container, zone) && container.getGridServiceAgent() != null
                    && container.getGridServiceAgent().getUid().equals(agentUid)) {

                containers.add(container);
            }
        }
        return containers;
    }

    public static boolean isContainerMatchesZone(GridServiceContainer container, String zone) {
        return container.getZones().containsKey(zone);
    }

    public static long getMemoryInMB(GridServiceContainer container) {

        String prefix = "-Xmx";
        String xmxArgument = getCommandLineArgumentRemovePrefix(container, prefix);
        if (xmxArgument == null) {
            throw new IllegalStateException("Container " + gscToString(container)
                    + " does not have an -Xmx commandline argument. If it was started manually please close it.");
        }
        return MemoryUnit.MEGABYTES.convert(xmxArgument);
    }

    public static String getCommandLineArgumentRemovePrefix(VirtualMachineAware container, String prefix) {
        String[] commandLineArguments = container.getVirtualMachine().getDetails().getInputArguments();
        String requiredArg = null;
        for (final String arg : commandLineArguments) {
            if (arg.startsWith(prefix)) {
                requiredArg = arg;
            }
        }

        if (requiredArg != null) {
            return requiredArg.substring(prefix.length());
        }
        return null;
    }

    public static String getContainerZone(ProcessingUnit pu) {
        String[] zones = pu.getRequiredZones();
        if (zones.length == 0) {
            throw new IllegalArgumentException("Elastic Processing Unit must have exactly one (container) zone. "
                    + pu.getName() + " has been deployed with no zones defined.");
        }

        if (zones.length > 1) {
            throw new IllegalArgumentException(
                    "Elastic Processing Unit must have exactly one (container) zone. " + pu.getName()
                            + " has been deployed with " + zones.length + " zones : " + Arrays.toString(zones));
        }

        return zones[0];
    }

    public static ProcessingUnit findProcessingUnitWithSameZone(Set<ProcessingUnit> processingUnits,
            ProcessingUnit pu) {
        for (final ProcessingUnit endpointPu : processingUnits) {
            if (ContainersSlaUtils.getContainerZone(endpointPu).equals(ContainersSlaUtils.getContainerZone(pu))) {
                return endpointPu;
            }
        }
        return null;
    }

    public static ProcessingUnit findProcessingUnitWithSameName(Set<ProcessingUnit> processingUnits,
            ProcessingUnit pu) {
        for (final ProcessingUnit endpointPu : processingUnits) {
            if (endpointPu.getName().equals(pu.getName())) {
                return endpointPu;
            }
        }
        return null;
    }

    public static String machineToString(Machine machine) {
        return MachinesSlaUtils.machineToString(machine);
    }

    public static String gscToString(GridComponent container) {
        String[] zones = container.getZones().keySet().toArray(new String[container.getZones().keySet().size()]);
        return "pid[" + container.getVirtualMachine().getDetails().getPid() + "] host["
                + machineToString(container.getMachine()) + "] zones [" + Arrays.toString(zones) + "]";
    }

    public static String gscsToString(GridServiceContainer[] containers) {
        String[] containersToString = new String[containers.length];
        for (int i = 0; i < containersToString.length; i++) {
            containersToString[i] = gscToString(containers[i]);
        }
        return Arrays.toString(containersToString);
    }

    public static String gscsToString(Collection<GridServiceContainer> containers) {
        return gscsToString(containers.toArray(new GridServiceContainer[containers.size()]));
    }
}