/*
* 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.apache.hadoop.hive.llap.registry.impl;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
import org.apache.hadoop.hive.llap.registry.ServiceInstanceSet;
import org.apache.hadoop.hive.llap.registry.ServiceInstanceStateChangeListener;
import org.apache.hadoop.hive.llap.registry.ServiceRegistry;
import org.apache.hadoop.registry.client.binding.RegistryUtils;
import org.apache.hadoop.service.AbstractService;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Preconditions;
public class LlapRegistryService extends AbstractService {
private static final Logger LOG = LoggerFactory.getLogger(LlapRegistryService.class);
private ServiceRegistry registry = null;
private final boolean isDaemon;
private boolean isDynamic = false;
private String identity = "(pending)";
private static final Map<String, LlapRegistryService> yarnRegistries = new HashMap<>();
public LlapRegistryService(boolean isDaemon) {
super("LlapRegistryService");
this.isDaemon = isDaemon;
}
/**
* Helper method to get a ServiceRegistry instance to read from the registry.
* This should not be used by LLAP daemons.
*
* @param conf {@link Configuration} instance which contains service registry information.
* @return
*/
public static synchronized LlapRegistryService getClient(Configuration conf) {
String hosts = HiveConf.getTrimmedVar(conf, HiveConf.ConfVars.LLAP_DAEMON_SERVICE_HOSTS);
Preconditions.checkNotNull(hosts, ConfVars.LLAP_DAEMON_SERVICE_HOSTS.toString() + " must be defined");
LlapRegistryService registry;
if (hosts.startsWith("@")) {
// Caching instances only in case of the YARN registry. Each host based list will get it's own copy.
String appName = hosts.substring(1);
String userName = HiveConf.getVar(conf, ConfVars.LLAP_ZK_REGISTRY_USER, currentUser());
String key = appName + "-" + userName;
registry = yarnRegistries.get(key);
if (registry == null || !registry.isInState(STATE.STARTED)) {
registry = new LlapRegistryService(false);
registry.init(conf);
registry.start();
yarnRegistries.put(key, registry);
}
} else {
registry = new LlapRegistryService(false);
registry.init(conf);
registry.start();
}
LOG.info("Using LLAP registry (client) type: " + registry);
return registry;
}
public static String currentUser() {
return RegistryUtils.currentUser();
}
@Override
public void serviceInit(Configuration conf) {
String hosts = HiveConf.getTrimmedVar(conf, ConfVars.LLAP_DAEMON_SERVICE_HOSTS);
if (hosts.startsWith("@")) {
registry = new LlapZookeeperRegistryImpl(hosts.substring(1), conf);
this.isDynamic=true;
} else {
registry = new LlapFixedRegistryImpl(hosts, conf);
this.isDynamic=false;
}
LOG.info("Using LLAP registry type " + registry);
}
@Override
public void serviceStart() throws Exception {
if (this.registry != null) {
this.registry.start();
}
if (isDaemon) {
registerWorker();
}
}
@Override
public void serviceStop() throws Exception {
if (isDaemon) {
unregisterWorker();
}
if (this.registry != null) {
this.registry.stop();
} else {
LOG.warn("Stopping non-existent registry service");
}
}
private void registerWorker() throws IOException {
if (this.registry != null) {
this.identity = this.registry.register();
}
}
private void unregisterWorker() throws IOException {
if (this.registry != null) {
this.registry.unregister();
}
}
public ServiceInstanceSet getInstances() throws IOException {
return getInstances(0);
}
public ServiceInstanceSet getInstances(long clusterReadyTimeoutMs) throws IOException {
return this.registry.getInstances("LLAP", clusterReadyTimeoutMs);
}
public void registerStateChangeListener(ServiceInstanceStateChangeListener listener)
throws IOException {
this.registry.registerStateChangeListener(listener);
}
// is the registry dynamic (i.e refreshes?)
public boolean isDynamic() {
return isDynamic;
}
// this is only useful for the daemons to know themselves
public String getWorkerIdentity() {
return identity;
}
public ApplicationId getApplicationId() throws IOException {
return registry.getApplicationId();
}
}