co.cask.cdap.common.twill.AbstractDistributedMasterServiceManager.java Source code

Java tutorial

Introduction

Here is the source code for co.cask.cdap.common.twill.AbstractDistributedMasterServiceManager.java

Source

/*
 * Copyright  2014 Cask Data, 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 co.cask.cdap.common.twill;

import co.cask.cdap.common.conf.CConfiguration;
import co.cask.cdap.common.conf.Constants;
import co.cask.cdap.proto.Containers;
import co.cask.cdap.proto.SystemServiceLiveInfo;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.Futures;
import org.apache.twill.api.ResourceReport;
import org.apache.twill.api.TwillController;
import org.apache.twill.api.TwillRunResources;
import org.apache.twill.api.TwillRunnerService;
import org.apache.twill.discovery.Discoverable;
import org.apache.twill.discovery.DiscoveryServiceClient;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.Collection;
import java.util.concurrent.TimeUnit;

/**
 * Abstract class that can be extended by individual CDAP Services to implement their management methods.
 */
public abstract class AbstractDistributedMasterServiceManager implements MasterServiceManager {
    private static final Logger LOG = LoggerFactory.getLogger(AbstractDistributedMasterServiceManager.class);
    private static final long SERVICE_PING_RESPONSE_TIMEOUT = TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS);
    protected final long discoveryTimeout;

    protected CConfiguration cConf;
    protected TwillRunnerService twillRunnerService;
    protected String serviceName;
    protected DiscoveryServiceClient discoveryServiceClient;

    public AbstractDistributedMasterServiceManager(CConfiguration cConf, String serviceName,
            TwillRunnerService twillRunnerService, DiscoveryServiceClient discoveryServiceClient) {
        this.cConf = cConf;
        this.serviceName = serviceName;
        this.twillRunnerService = twillRunnerService;
        this.discoveryTimeout = cConf.getLong(Constants.Monitor.DISCOVERY_TIMEOUT_SECONDS);
        this.discoveryServiceClient = discoveryServiceClient;
    }

    @Override
    public SystemServiceLiveInfo getLiveInfo() {
        SystemServiceLiveInfo.Builder builder = SystemServiceLiveInfo.builder();

        Iterable<TwillController> twillControllerList = twillRunnerService
                .lookup(Constants.Service.MASTER_SERVICES);
        if (twillControllerList == null) {
            return builder.build();
        }

        for (TwillController twillController : twillControllerList) {
            if (twillController.getResourceReport() == null) {
                continue;
            }

            ResourceReport resourceReport = twillController.getResourceReport();
            Collection<TwillRunResources> runResources = resourceReport.getResources().get(serviceName);
            for (TwillRunResources resources : runResources) {
                Containers.ContainerInfo containerInfo = new Containers.ContainerInfo(
                        Containers.ContainerType.SYSTEM_SERVICE, serviceName, resources.getInstanceId(),
                        resources.getContainerId(), resources.getHost(), resources.getMemoryMB(),
                        resources.getVirtualCores(), resources.getDebugPort());
                builder.addContainer(containerInfo);
            }
        }
        return builder.build();
    }

    @Override
    public int getInstances() {
        Iterable<TwillController> twillControllerList = twillRunnerService
                .lookup(Constants.Service.MASTER_SERVICES);
        int instances = 0;
        if (twillControllerList != null) {
            for (TwillController twillController : twillControllerList) {
                if (twillController.getResourceReport() != null) {
                    instances = twillController.getResourceReport().getRunnableResources(serviceName).size();
                }
            }
        }
        return instances;
    }

    public boolean isServiceEnabled() {
        // By default all the services are enabled. extending classes can override if the behavior should be different.
        return true;
    }

    @Override
    public boolean setInstances(int instanceCount) {
        Preconditions.checkArgument(instanceCount > 0);
        try {
            Iterable<TwillController> twillControllerList = twillRunnerService
                    .lookup(Constants.Service.MASTER_SERVICES);
            if (twillControllerList != null) {
                for (TwillController twillController : twillControllerList) {
                    twillController.changeInstances(serviceName, instanceCount).get();
                }
            }
            return true;
        } catch (Throwable t) {
            LOG.error("Could not change service instance of {} : {}", serviceName, t.getMessage(), t);
            return false;
        }
    }

    @Override
    public int getMinInstances() {
        return 1;
    }

    @Override
    public boolean canCheckStatus() {
        return true;
    }

    @Override
    public boolean isLogAvailable() {
        return true;
    }

    @Override
    public boolean isServiceAvailable() {
        try {
            Iterable<Discoverable> discoverables = this.discoveryServiceClient.discover(serviceName);
            for (Discoverable discoverable : discoverables) {
                //Ping the discovered service to check its status.
                String url = String.format("http://%s:%d/ping", discoverable.getSocketAddress().getHostName(),
                        discoverable.getSocketAddress().getPort());
                if (checkGetStatus(url).equals(HttpResponseStatus.OK)) {
                    return true;
                }
            }
            return false;
        } catch (IllegalArgumentException e) {
            return false;
        } catch (Exception e) {
            LOG.warn("Unable to ping {} : Reason : {}", serviceName, e.getMessage());
            return false;
        }
    }

    protected final HttpResponseStatus checkGetStatus(String url) throws Exception {
        HttpURLConnection httpConn = null;
        try {
            httpConn = (HttpURLConnection) new URL(url).openConnection();
            httpConn.setConnectTimeout((int) SERVICE_PING_RESPONSE_TIMEOUT);
            httpConn.setReadTimeout((int) SERVICE_PING_RESPONSE_TIMEOUT);
            return (HttpResponseStatus.valueOf(httpConn.getResponseCode()));
        } catch (SocketTimeoutException e) {
            return HttpResponseStatus.NOT_FOUND;
        } finally {
            if (httpConn != null) {
                httpConn.disconnect();
            }
        }
    }

    @Override
    public void restartAllInstances() {
        Iterable<TwillController> twillControllers = twillRunnerService.lookup(Constants.Service.MASTER_SERVICES);
        for (TwillController twillController : twillControllers) {
            // Call restart instances
            Futures.getUnchecked(twillController.restartAllInstances(serviceName));
        }
    }

    @Override
    public void restartInstances(int instanceId, int... moreInstanceIds) {
        Iterable<TwillController> twillControllers = twillRunnerService.lookup(Constants.Service.MASTER_SERVICES);
        for (TwillController twillController : twillControllers) {
            // Call restart instances
            Futures.getUnchecked(twillController.restartInstances(serviceName, instanceId, moreInstanceIds));
        }
    }
}