blob: 909006883428de85caff5caac9460017ac26ee47 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.kylin.common;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Properties;
import java.util.SortedSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.kylin.common.util.CliCommandExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Sets;
@SuppressWarnings("serial")
/**
* An abstract class to encapsulate access to a set of 'properties'.
* Subclass can override methods in this class to extend the content of the 'properties',
* with some override values for example.
*/
abstract public class KylinConfigBase implements Serializable {
private static final Logger logger = LoggerFactory.getLogger(KylinConfigBase.class);
/*
* DON'T DEFINE CONSTANTS FOR PROPERTY KEYS!
*
* For 1), no external need to access property keys, all accesses are by public methods.
* For 2), it's cumbersome to maintain constants at top and code at bottom.
* For 3), key literals usually appear only once.
*/
public static String getKylinHome() {
String kylinHome = System.getenv("KYLIN_HOME");
if (StringUtils.isEmpty(kylinHome)) {
logger.warn("KYLIN_HOME was not set");
}
return kylinHome;
}
// ============================================================================
private volatile Properties properties = new Properties();
public KylinConfigBase() {
this(new Properties());
}
public KylinConfigBase(Properties props) {
this.properties = props;
}
final protected String getOptional(String prop) {
return getOptional(prop, null);
}
protected String getOptional(String prop, String dft) {
final String property = System.getProperty(prop);
return property != null ? property : properties.getProperty(prop, dft);
}
protected Properties getAllProperties() {
return properties;
}
final protected String[] getOptionalStringArray(String prop, String[] dft) {
final String property = getOptional(prop);
if (!StringUtils.isBlank(property)) {
return property.split("\\s*,\\s*");
} else {
return dft;
}
}
final public String getRequired(String prop) {
String r = getOptional(prop);
if (StringUtils.isEmpty(r)) {
throw new IllegalArgumentException("missing '" + prop + "' in conf/kylin.properties");
}
return r;
}
/**
* Use with care, properties should be read-only. This is for testing mostly.
*/
final public void setProperty(String key, String value) {
logger.info("Kylin Config was updated with " + key + " : " + value);
properties.setProperty(key, value);
}
final protected void reloadKylinConfig(InputStream is) {
Properties newProperties = new Properties();
try {
newProperties.load(is);
} catch (IOException e) {
throw new RuntimeException("Cannot load kylin config.", e);
} finally {
IOUtils.closeQuietly(is);
}
this.properties = newProperties;
}
// ============================================================================
public boolean isDevEnv() {
return "DEV".equals(getOptional("deploy.env", "DEV"));
}
public String getMetadataUrl() {
return getOptional("kylin.metadata.url");
}
public void setMetadataUrl(String metadataUrl) {
setProperty("kylin.metadata.url", metadataUrl);
}
public String getMetadataUrlPrefix() {
String hbaseMetadataUrl = getMetadataUrl();
String defaultPrefix = "kylin_metadata";
if (org.apache.commons.lang3.StringUtils.containsIgnoreCase(hbaseMetadataUrl, "@hbase")) {
int cut = hbaseMetadataUrl.indexOf('@');
String tmp = cut < 0 ? defaultPrefix : hbaseMetadataUrl.substring(0, cut);
return tmp;
} else {
return defaultPrefix;
}
}
public String getServerMode() {
return this.getOptional("kylin.server.mode", "all");
}
public String getStorageUrl() {
return getOptional("kylin.storage.url");
}
public void setStorageUrl(String storageUrl) {
setProperty("kylin.storage.url", storageUrl);
}
/** was for route to hive, not used any more */
@Deprecated
public String getHiveUrl() {
return getOptional("hive.url", "");
}
/** was for route to hive, not used any more */
@Deprecated
public String getHiveUser() {
return getOptional("hive.user", "");
}
/** was for route to hive, not used any more */
@Deprecated
public String getHivePassword() {
return getOptional("hive.password", "");
}
public String getHdfsWorkingDirectory() {
String root = getRequired("kylin.hdfs.working.dir");
if (!root.endsWith("/")) {
root += "/";
}
return new StringBuffer(root).append(StringUtils.replaceChars(getMetadataUrlPrefix(), ':', '-')).append("/").toString();
}
public CliCommandExecutor getCliCommandExecutor() throws IOException {
CliCommandExecutor exec = new CliCommandExecutor();
if (getRunAsRemoteCommand()) {
exec.setRunAtRemote(getRemoteHadoopCliHostname(), getRemoteHadoopCliPort(), getRemoteHadoopCliUsername(), getRemoteHadoopCliPassword());
}
return exec;
}
public String getHBaseClusterFs() {
return getOptional("kylin.hbase.cluster.fs", "");
}
public String getKylinJobLogDir() {
return getOptional("kylin.job.log.dir", "/tmp/kylin/logs");
}
public String getKylinJobJarPath() {
final String jobJar = getOptional("kylin.job.jar");
if (StringUtils.isNotEmpty(jobJar)) {
return jobJar;
}
String kylinHome = getKylinHome();
if (StringUtils.isEmpty(kylinHome)) {
return "";
}
return getFileName(kylinHome + File.separator + "lib", JOB_JAR_NAME_PATTERN);
}
public void overrideMRJobJarPath(String path) {
logger.info("override " + "kylin.job.jar" + " to " + path);
System.setProperty("kylin.job.jar", path);
}
public String getKylinJobMRLibDir() {
return getOptional("kylin.job.mr.lib.dir", "");
}
public String getKylinSparkJobJarPath() {
final String jobJar = getOptional("kylin.job.jar.spark");
if (StringUtils.isNotEmpty(jobJar)) {
return jobJar;
}
String kylinHome = getKylinHome();
if (StringUtils.isEmpty(kylinHome)) {
return "";
}
return getFileName(kylinHome + File.separator + "lib", SPARK_JOB_JAR_NAME_PATTERN);
}
public void overrideSparkJobJarPath(String path) {
logger.info("override " + "kylin.job.jar.spark" + " to " + path);
System.setProperty("kylin.job.jar.spark", path);
}
private static final Pattern COPROCESSOR_JAR_NAME_PATTERN = Pattern.compile("kylin-coprocessor-(.+)\\.jar");
private static final Pattern JOB_JAR_NAME_PATTERN = Pattern.compile("kylin-job-(.+)\\.jar");
private static final Pattern SPARK_JOB_JAR_NAME_PATTERN = Pattern.compile("kylin-engine-spark-(.+)\\.jar");
public String getCoprocessorLocalJar() {
final String coprocessorJar = getOptional("kylin.coprocessor.local.jar");
if (StringUtils.isNotEmpty(coprocessorJar)) {
return coprocessorJar;
}
String kylinHome = getKylinHome();
if (StringUtils.isEmpty(kylinHome)) {
throw new RuntimeException("getCoprocessorLocalJar needs KYLIN_HOME");
}
return getFileName(kylinHome + File.separator + "lib", COPROCESSOR_JAR_NAME_PATTERN);
}
public void overrideCoprocessorLocalJar(String path) {
logger.info("override " + "kylin.coprocessor.local.jar" + " to " + path);
System.setProperty("kylin.coprocessor.local.jar", path);
}
private static String getFileName(String homePath, Pattern pattern) {
File home = new File(homePath);
SortedSet<String> files = Sets.newTreeSet();
if (home.exists() && home.isDirectory()) {
for (File file : home.listFiles()) {
final Matcher matcher = pattern.matcher(file.getName());
if (matcher.matches()) {
files.add(file.getAbsolutePath());
}
}
}
if (files.isEmpty()) {
throw new RuntimeException("cannot find " + pattern.toString() + " in " + homePath);
} else {
return files.last();
}
}
public double getDefaultHadoopJobReducerInputMB() {
return Double.parseDouble(getOptional("kylin.job.mapreduce.default.reduce.input.mb", "500"));
}
public double getDefaultHadoopJobReducerCountRatio() {
return Double.parseDouble(getOptional("kylin.job.mapreduce.default.reduce.count.ratio", "1.0"));
}
public int getHadoopJobMaxReducerNumber() {
return Integer.parseInt(getOptional("kylin.job.mapreduce.max.reducer.number", "500"));
}
public boolean getRunAsRemoteCommand() {
return Boolean.parseBoolean(getOptional("kylin.job.run.as.remote.cmd"));
}
public void setRunAsRemoteCommand(String v) {
setProperty("kylin.job.run.as.remote.cmd", v);
}
public int getRemoteHadoopCliPort() {
return Integer.parseInt(getOptional("kylin.job.remote.cli.port", "22"));
}
public String getRemoteHadoopCliHostname() {
return getOptional("kylin.job.remote.cli.hostname");
}
public void setRemoteHadoopCliHostname(String v) {
setProperty("kylin.job.remote.cli.hostname", v);
}
public String getRemoteHadoopCliUsername() {
return getOptional("kylin.job.remote.cli.username");
}
public void setRemoteHadoopCliUsername(String v) {
setProperty("kylin.job.remote.cli.username", v);
}
public String getRemoteHadoopCliPassword() {
return getOptional("kylin.job.remote.cli.password");
}
public void setRemoteHadoopCliPassword(String v) {
setProperty("kylin.job.remote.cli.password", v);
}
public String getCliWorkingDir() {
return getOptional("kylin.job.remote.cli.working.dir");
}
public String getMapReduceCmdExtraArgs() {
return getOptional("kylin.job.cmd.extra.args");
}
public String getOverrideHiveTableLocation(String table) {
return getOptional("hive.table.location." + table.toUpperCase());
}
public String getYarnStatusCheckUrl() {
return getOptional("kylin.job.yarn.app.rest.check.status.url", null);
}
public int getYarnStatusCheckIntervalSeconds() {
return Integer.parseInt(getOptional("kylin.job.yarn.app.rest.check.interval.seconds", "60"));
}
public int getMaxConcurrentJobLimit() {
return Integer.parseInt(getOptional("kylin.job.concurrent.max.limit", "10"));
}
public String getTimeZone() {
return getOptional("kylin.rest.timezone", "PST");
}
public String[] getRestServers() {
return getOptionalStringArray("kylin.rest.servers", new String[0]);
}
public int getWorkersPerServer() {
//for sequence sql use
return Integer.parseInt(getOptional("kylin.rest.workers.per.server", "1"));
}
public String[] getAdminDls() {
return getOptionalStringArray("kylin.job.admin.dls", null);
}
public long getJobStepTimeout() {
return Long.parseLong(getOptional("kylin.job.step.timeout", String.valueOf(2 * 60 * 60)));
}
public String getCubeAlgorithm() {
return getOptional("kylin.cube.algorithm", "auto");
}
public double getCubeAlgorithmAutoThreshold() {
return Double.parseDouble(getOptional("kylin.cube.algorithm.auto.threshold", "8"));
}
@Deprecated
public int getCubeAggrGroupMaxSize() {
return Integer.parseInt(getOptional("kylin.cube.aggrgroup.max.size", "12"));
}
public int getCubeAggrGroupMaxCombination() {
return Integer.parseInt(getOptional("kylin.cube.aggrgroup.max.combination", "4096"));
}
public String[] getCubeDimensionCustomEncodingFactories() {
return getOptionalStringArray("kylin.cube.dimension.customEncodingFactories", new String[0]);
}
public int getDictionaryMaxCardinality() {
return Integer.parseInt(getOptional("kylin.dictionary.max.cardinality", "5000000"));
}
public int getTableSnapshotMaxMB() {
return Integer.parseInt(getOptional("kylin.table.snapshot.max_mb", "300"));
}
public int getHBaseRegionCountMin() {
return Integer.parseInt(getOptional("kylin.hbase.region.count.min", "1"));
}
public int getHBaseRegionCountMax() {
return Integer.parseInt(getOptional("kylin.hbase.region.count.max", "500"));
}
public void setHBaseHFileSizeGB(float size) {
setProperty("kylin.hbase.hfile.size.gb", String.valueOf(size));
}
public float getHBaseHFileSizeGB() {
return Float.parseFloat(getOptional("kylin.hbase.hfile.size.gb", "2.0"));
}
public int getScanThreshold() {
return Integer.parseInt(getOptional("kylin.query.scan.threshold", "10000000"));
}
public int getCubeVisitTimeoutTimes() {
return Integer.parseInt(getOptional("kylin.query.cube.visit.timeout.times", "1"));
}
public int getBadQueryStackTraceDepth() {
return Integer.parseInt(getOptional("kylin.query.badquery.stacktrace.depth", "10"));
}
public int getBadQueryHistoryNum() {
return Integer.parseInt(getOptional("kylin.query.badquery.history.num", "10"));
}
public int getBadQueryDefaultAlertingSeconds() {
return Integer.parseInt(getOptional("kylin.query.badquery.alerting.seconds", "90"));
}
public int getBadQueryDefaultDetectIntervalSeconds() {
return Integer.parseInt(getOptional("kylin.query.badquery.detect.interval.seconds", "60"));
}
public boolean getBadQueryPersistentEnabled() {
return Boolean.parseBoolean(getOptional("kylin.query.badquery.persistent.enable", "true"));
}
public int getCachedDictMaxEntrySize() {
return Integer.parseInt(getOptional("kylin.dict.cache.max.entry", "3000"));
}
public boolean getQueryRunLocalCoprocessor() {
return Boolean.parseBoolean(getOptional("kylin.query.run.local.coprocessor", "false"));
}
public Long getQueryDurationCacheThreshold() {
return Long.parseLong(this.getOptional("kylin.query.cache.threshold.duration", String.valueOf(2000)));
}
public Long getQueryScanCountCacheThreshold() {
return Long.parseLong(this.getOptional("kylin.query.cache.threshold.scancount", String.valueOf(10 * 1024)));
}
public long getQueryMemBudget() {
return Long.parseLong(this.getOptional("kylin.query.mem.budget", String.valueOf(3L * 1024 * 1024 * 1024)));
}
public double getQueryCoprocessorMemGB() {
return Double.parseDouble(this.getOptional("kylin.query.coprocessor.mem.gb", "3.0"));
}
public boolean isQuerySecureEnabled() {
return Boolean.parseBoolean(this.getOptional("kylin.query.security.enabled", "true"));
}
public boolean isQueryCacheEnabled() {
return Boolean.parseBoolean(this.getOptional("kylin.query.cache.enabled", "true"));
}
public boolean isQueryIgnoreUnknownFunction() {
return Boolean.parseBoolean(this.getOptional("kylin.query.ignore_unknown_function", "false"));
}
public String getQueryStorageVisitPlanner() {
return this.getOptional("kylin.query.storage.visit.planner", "org.apache.kylin.gridtable.GTScanRangePlanner");
}
public void setQueryStorageVisitPlanner(String v) {
setProperty("kylin.query.storage.visit.planner", v);
}
public int getQueryScanFuzzyKeyMax() {
return Integer.parseInt(this.getOptional("kylin.query.scan.fuzzykey.max", "200"));
}
public int getQueryStorageVisitScanRangeMax() {
return Integer.valueOf(this.getOptional("kylin.query.storage.visit.scanrange.max", "1000000"));
}
public long getSequenceExpireTime() {
return Long.valueOf(this.getOptional("kylin.query.sequence.expire.time", "86400000"));//default a day
}
public int getHBaseKeyValueSize() {
return Integer.parseInt(this.getOptional("kylin.hbase.client.keyvalue.maxsize", "10485760"));
}
public String getDefaultIGTStorage() {
return getOptional("kylin.query.storage.default.gtstorage", "org.apache.kylin.storage.hbase.cube.v2.CubeHBaseEndpointRPC");
}
public int getHBaseScanCacheRows() {
return Integer.parseInt(this.getOptional("kylin.hbase.scan.cache_rows", "1024"));
}
public boolean isGrowingDictEnabled() {
return Boolean.parseBoolean(this.getOptional("kylin.dict.growing.enabled", "false"));
}
/**
* HBase region cut size, in GB
* @return
*/
public float getKylinHBaseRegionCut() {
return Float.valueOf(getOptional("kylin.hbase.region.cut", "5.0"));
}
public int getHBaseScanMaxResultSize() {
return Integer.parseInt(this.getOptional("kylin.hbase.scan.max_result_size", "" + (5 * 1024 * 1024))); // 5 MB
}
public int getCubingInMemSamplingPercent() {
int percent = Integer.parseInt(this.getOptional("kylin.job.cubing.inmem.sampling.percent", "100"));
percent = Math.max(percent, 1);
percent = Math.min(percent, 100);
return percent;
}
public String getHbaseDefaultCompressionCodec() {
return getOptional("kylin.hbase.default.compression.codec", "");
}
public String getHbaseDefaultEncoding() {
return getOptional("kylin.hbase.default.encoding", "FAST_DIFF");
}
public int getHbaseDefaultBlockSize() {
return Integer.valueOf(getOptional("kylin.hbase.default.block.size", "1048576"));
}
public int getHbaseSmallFamilyBlockSize() {
return Integer.valueOf(getOptional("kylin.hbase.small.family.block.size", "65536"));
}
public boolean isHiveKeepFlatTable() {
return Boolean.parseBoolean(this.getOptional("kylin.hive.keep.flat.table", "false"));
}
public String getHiveDatabaseForIntermediateTable() {
return this.getOptional("kylin.job.hive.database.for.intermediatetable", "default");
}
public boolean isGetJobStatusWithKerberos() {
return Boolean.valueOf(this.getOptional("kylin.job.status.with.kerberos", "false"));
}
public String getKylinOwner() {
return this.getOptional("kylin.owner", "");
}
public String getSparkHome() {
return getRequired("kylin.spark.home");
}
public String getSparkMaster() {
return getRequired("kylin.spark.master");
}
public boolean isMailEnabled() {
return Boolean.parseBoolean(getOptional("mail.enabled", "false"));
}
public void setMailEnabled(boolean enable) {
setProperty("mail.enabled", "" + enable);
}
public String getMailHost() {
return getOptional("mail.host", "");
}
public String getMailUsername() {
return getOptional("mail.username", "");
}
public String getMailPassword() {
return getOptional("mail.password", "");
}
public String getMailSender() {
return getOptional("mail.sender", "");
}
public boolean isWebCrossDomainEnabled() {
return Boolean.parseBoolean(getOptional("crossdomain.enable", "true"));
}
public int getJobRetry() {
return Integer.parseInt(this.getOptional("kylin.job.retry", "0"));
}
public String toString() {
return getMetadataUrl();
}
public String getHiveClientMode() {
return getOptional("kylin.hive.client", "cli");
}
public String getHiveBeelineParams() {
return getOptional("kylin.hive.beeline.params", "");
}
public String getDeployEnv() {
return getOptional("deploy.env", "DEV");
}
public String getInitTasks() {
return getOptional("kylin.init.tasks");
}
public String getMRBatchEngineV1Class() {
return getOptional("kylin.cube.mr.engine.v1.class", "org.apache.kylin.engine.mr.MRBatchCubingEngine");
}
public String getMRBatchEngineV2Class() {
return getOptional("kylin.cube.mr.engine.v2.class", "org.apache.kylin.engine.mr.MRBatchCubingEngine2");
}
public int getDimCountDistinctMaxCardinality() {
return Integer.parseInt(getOptional("kylin.query.dim.distinct.max", "5000000"));
}
public int getCubeStatsHLLPrecision() {
return Integer.parseInt(getOptional("kylin.job.cubing.inmem.sampling.hll.precision", "14"));
}
public String getPatchedFuzzyRowFilterVersion() {
return this.getOptional("kylin.hbase.filter.fuzzy.row.filter.version", "1.1.3");
}
}