Repository: kylin Updated Branches: refs/heads/master 0d46e4a27 -> 4d1676a66
KYLIN-2312 display server config/environment by order in system tab Project: http://git-wip-us.apache.org/repos/asf/kylin/repo Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/4d1676a6 Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/4d1676a6 Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/4d1676a6 Branch: refs/heads/master Commit: 4d1676a66889283647b7c63022505234fa9d328c Parents: 0d46e4a Author: Billy Liu <billy...@apache.org> Authored: Thu Dec 22 18:55:51 2016 +0800 Committer: Billy Liu <billy...@apache.org> Committed: Thu Dec 22 18:55:51 2016 +0800 ---------------------------------------------------------------------- .../common/BackwardCompatibilityConfig.java | 9 + .../org/apache/kylin/common/KylinConfig.java | 21 +- .../kylin/common/util/OrderedProperties.java | 388 +++++++++++++++++++ .../kylin/job/constant/ExecutableConstants.java | 4 - .../apache/kylin/rest/service/AdminService.java | 16 +- 5 files changed, 417 insertions(+), 21 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kylin/blob/4d1676a6/core-common/src/main/java/org/apache/kylin/common/BackwardCompatibilityConfig.java ---------------------------------------------------------------------- diff --git a/core-common/src/main/java/org/apache/kylin/common/BackwardCompatibilityConfig.java b/core-common/src/main/java/org/apache/kylin/common/BackwardCompatibilityConfig.java index 21df932..426ebb9 100644 --- a/core-common/src/main/java/org/apache/kylin/common/BackwardCompatibilityConfig.java +++ b/core-common/src/main/java/org/apache/kylin/common/BackwardCompatibilityConfig.java @@ -29,6 +29,7 @@ import java.util.Properties; import java.util.Stack; import org.apache.commons.io.IOUtils; +import org.apache.kylin.common.util.OrderedProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -121,6 +122,14 @@ public class BackwardCompatibilityConfig { return result; } + public OrderedProperties check(OrderedProperties props){ + OrderedProperties result = new OrderedProperties(); + for (Entry<String, String> kv : props.entrySet()) { + result.setProperty(check(kv.getKey()), kv.getValue()); + } + return result; + } + // ============================================================================ public static void main(String[] args) throws IOException { http://git-wip-us.apache.org/repos/asf/kylin/blob/4d1676a6/core-common/src/main/java/org/apache/kylin/common/KylinConfig.java ---------------------------------------------------------------------- diff --git a/core-common/src/main/java/org/apache/kylin/common/KylinConfig.java b/core-common/src/main/java/org/apache/kylin/common/KylinConfig.java index acd4398..f169142 100644 --- a/core-common/src/main/java/org/apache/kylin/common/KylinConfig.java +++ b/core-common/src/main/java/org/apache/kylin/common/KylinConfig.java @@ -25,7 +25,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.io.StringReader; -import java.io.StringWriter; import java.nio.charset.Charset; import java.util.Enumeration; import java.util.Map; @@ -35,6 +34,7 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.apache.kylin.common.restclient.RestClient; import org.apache.kylin.common.util.ClassUtil; +import org.apache.kylin.common.util.OrderedProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -282,18 +282,15 @@ public class KylinConfig extends KylinConfigBase { } public String getConfigAsString() throws IOException { - final StringWriter stringWriter = new StringWriter(); - list(new PrintWriter(stringWriter)); - return stringWriter.toString(); - } - - private void list(PrintWriter out) { - Properties props = getAllProperties(); - for (Enumeration<?> e = props.keys(); e.hasMoreElements();) { - String key = (String) e.nextElement(); - String val = (String) props.get(key); - out.println(key + "=" + val); + File propertiesFile = getKylinPropertiesFile(); + OrderedProperties orderedProperties = new OrderedProperties(); + orderedProperties.load(new FileInputStream(propertiesFile)); + orderedProperties = BCC.check(orderedProperties); + final StringBuilder sb = new StringBuilder(); + for (Map.Entry<String, String> entry : orderedProperties.entrySet()) { + sb.append(entry.getKey() + "=" + entry.getValue()).append('\n'); } + return sb.toString(); } public KylinConfig base() { http://git-wip-us.apache.org/repos/asf/kylin/blob/4d1676a6/core-common/src/main/java/org/apache/kylin/common/util/OrderedProperties.java ---------------------------------------------------------------------- diff --git a/core-common/src/main/java/org/apache/kylin/common/util/OrderedProperties.java b/core-common/src/main/java/org/apache/kylin/common/util/OrderedProperties.java new file mode 100644 index 0000000..0e5a3f9 --- /dev/null +++ b/core-common/src/main/java/org/apache/kylin/common/util/OrderedProperties.java @@ -0,0 +1,388 @@ +/* + * 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.util; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.Serializable; +import java.io.Writer; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.InvalidPropertiesFormatException; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.TreeMap; +import java.util.Vector; + +/** + * Modified from the etiennestuder/java-ordered-properties in https://github.com/etiennestuder/java-ordered-properties + * + * This class provides an alternative to the JDK's {@link Properties} class. It fixes the design flaw of using + * inheritance over composition, while keeping up the same APIs as the original class. Keys and values are + * guaranteed to be of type {@link String}. + * <p/> + * This class is not synchronized, contrary to the original implementation. + * <p/> + * As additional functionality, this class keeps its properties in a well-defined order. By default, the order + * is the one in which the individual properties have been added, either through explicit API calls or through + * reading them top-to-bottom from a properties file. + * <p/> + * Currently, this class does not support the concept of default properties, contrary to the original implementation. + * <p/> + * <strong>Note that this implementation is not synchronized.</strong> If multiple threads access ordered + * properties concurrently, and at least one of the threads modifies the ordered properties structurally, it + * <em>must</em> be synchronized externally. This is typically accomplished by synchronizing on some object + * that naturally encapsulates the properties. + * <p/> + * Note that the actual (and quite complex) logic of parsing and storing properties from and to a stream + * is delegated to the {@link Properties} class from the JDK. + * + * @see Properties + */ +public final class OrderedProperties implements Serializable { + + private static final long serialVersionUID = 1L; + + private transient Map<String, String> properties; + + public OrderedProperties() { + this(new LinkedHashMap<String, String>()); + } + + public OrderedProperties(Map<String, String> properties) { + this.properties = properties; + } + + /** + * Creates a new instance that will have both the same property entries and + * the same behavior as the given source. + * <p/> + * Note that the source instance and the copy instance will share the same + * comparator instance if a custom ordering had been configured on the source. + * + * @param source the source to copy from + * @return the copy + */ + public static OrderedProperties copyOf(OrderedProperties source) { + // create a copy that has the same behaviour + OrderedPropertiesBuilder builder = new OrderedPropertiesBuilder(); + if (source.properties instanceof TreeMap) { + builder.withOrdering(((TreeMap<String, String>) source.properties).comparator()); + } + OrderedProperties result = builder.build(); + + // copy the properties from the source to the target + for (Map.Entry<String, String> entry : source.entrySet()) { + result.setProperty(entry.getKey(), entry.getValue()); + } + return result; + } + + /** + * See {@link Properties#getProperty(String)}. + */ + public String getProperty(String key) { + return properties.get(key); + } + + /** + * See {@link Properties#getProperty(String, String)}. + */ + public String getProperty(String key, String defaultValue) { + String value = properties.get(key); + return (value == null) ? defaultValue : value; + } + + /** + * See {@link Properties#setProperty(String, String)}. + */ + public String setProperty(String key, String value) { + return properties.put(key, value); + } + + /** + * Removes the property with the specified key, if it is present. Returns + * the value of the property, or <tt>null</tt> if there was no property with + * the specified key. + * + * @param key the key of the property to remove + * @return the previous value of the property, or <tt>null</tt> if there was no property with the specified key + */ + public String removeProperty(String key) { + return properties.remove(key); + } + + /** + * Returns <tt>true</tt> if there is a property with the specified key. + * + * @param key the key whose presence is to be tested + */ + public boolean containsProperty(String key) { + return properties.containsKey(key); + } + + /** + * See {@link Properties#size()}. + */ + public int size() { + return properties.size(); + } + + /** + * See {@link Properties#isEmpty()}. + */ + public boolean isEmpty() { + return properties.isEmpty(); + } + + /** + * See {@link Properties#propertyNames()}. + */ + public Enumeration<String> propertyNames() { + return new Vector<String>(properties.keySet()).elements(); + } + + /** + * See {@link Properties#stringPropertyNames()}. + */ + public Set<String> stringPropertyNames() { + return new LinkedHashSet<String>(properties.keySet()); + } + + /** + * See {@link Properties#entrySet()}. + */ + public Set<Map.Entry<String, String>> entrySet() { + return new LinkedHashSet<Map.Entry<String, String>>(properties.entrySet()); + } + + /** + * See {@link Properties#load(InputStream)}. + */ + public void load(InputStream stream) throws IOException { + CustomProperties customProperties = new CustomProperties(this.properties); + customProperties.load(stream); + } + + /** + * See {@link Properties#load(Reader)}. + */ + public void load(Reader reader) throws IOException { + CustomProperties customProperties = new CustomProperties(this.properties); + customProperties.load(reader); + } + + /** + * See {@link Properties#loadFromXML(InputStream)}. + */ + @SuppressWarnings("DuplicateThrows") + public void loadFromXML(InputStream stream) throws IOException, InvalidPropertiesFormatException { + CustomProperties customProperties = new CustomProperties(this.properties); + customProperties.loadFromXML(stream); + } + + /** + * See {@link Properties#store(OutputStream, String)}. + */ + public void store(OutputStream stream, String comments) throws IOException { + CustomProperties customProperties = new CustomProperties(this.properties); + customProperties.store(stream, comments); + } + + /** + * See {@link Properties#store(Writer, String)}. + */ + public void store(Writer writer, String comments) throws IOException { + CustomProperties customProperties = new CustomProperties(this.properties); + customProperties.store(writer, comments); + } + + /** + * See {@link Properties#storeToXML(OutputStream, String)}. + */ + public void storeToXML(OutputStream stream, String comment) throws IOException { + CustomProperties customProperties = new CustomProperties(this.properties); + customProperties.storeToXML(stream, comment); + } + + /** + * See {@link Properties#storeToXML(OutputStream, String, String)}. + */ + public void storeToXML(OutputStream stream, String comment, String encoding) throws IOException { + CustomProperties customProperties = new CustomProperties(this.properties); + customProperties.storeToXML(stream, comment, encoding); + } + + /** + * See {@link Properties#list(PrintStream)}. + */ + public void list(PrintStream stream) { + CustomProperties customProperties = new CustomProperties(this.properties); + customProperties.list(stream); + } + + /** + * See {@link Properties#list(PrintWriter)}. + */ + public void list(PrintWriter writer) { + CustomProperties customProperties = new CustomProperties(this.properties); + customProperties.list(writer); + } + + /** + * Convert this instance to a {@link Properties} instance. + * + * @return the {@link Properties} instance + */ + public Properties toJdkProperties() { + Properties jdkProperties = new Properties(); + for (Map.Entry<String, String> entry : this.entrySet()) { + jdkProperties.put(entry.getKey(), entry.getValue()); + } + return jdkProperties; + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + + if (other == null || getClass() != other.getClass()) { + return false; + } + + OrderedProperties that = (OrderedProperties) other; + return Arrays.equals(properties.entrySet().toArray(), that.properties.entrySet().toArray()); + } + + @Override + public int hashCode() { + return Arrays.hashCode(properties.entrySet().toArray()); + } + + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + stream.writeObject(properties); + } + + @SuppressWarnings("unchecked") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + properties = (Map<String, String>) stream.readObject(); + } + + private void readObjectNoData() throws InvalidObjectException { + throw new InvalidObjectException("Stream data required"); + } + + /** + * See {@link Properties#toString()}. + */ + @Override + public String toString() { + return properties.toString(); + } + + public Map<String, String> getProperties() { + return properties; + } + + /** + * Builder for {@link OrderedProperties} instances. + */ + public static final class OrderedPropertiesBuilder { + + private Comparator<? super String> comparator; + + /** + * Use a custom ordering of the keys. + * + * @param comparator the ordering to apply on the keys + * @return the builder + */ + public OrderedPropertiesBuilder withOrdering(Comparator<? super String> comparator) { + this.comparator = comparator; + return this; + } + + /** + * Builds a new {@link OrderedProperties} instance. + * + * @return the new instance + */ + public OrderedProperties build() { + Map<String, String> properties = (this.comparator != null) ? new TreeMap<String, String>(comparator) : new LinkedHashMap<String, String>(); + return new OrderedProperties(properties); + } + + } + + /** + * Custom {@link Properties} that delegates reading, writing, and enumerating properties to the + * backing {@link OrderedProperties} instance's properties. + */ + private static final class CustomProperties extends Properties { + + private final Map<String, String> targetProperties; + + private CustomProperties(Map<String, String> targetProperties) { + this.targetProperties = targetProperties; + } + + @Override + public Object get(Object key) { + return targetProperties.get(key); + } + + @Override + public Object put(Object key, Object value) { + return targetProperties.put((String) key, (String) value); + } + + @Override + public String getProperty(String key) { + return targetProperties.get(key); + } + + @Override + public Enumeration<Object> keys() { + return new Vector<Object>(targetProperties.keySet()).elements(); + } + + @SuppressWarnings("NullableProblems") + @Override + public Set<Object> keySet() { + return new LinkedHashSet<Object>(targetProperties.keySet()); + } + + } + +} http://git-wip-us.apache.org/repos/asf/kylin/blob/4d1676a6/core-job/src/main/java/org/apache/kylin/job/constant/ExecutableConstants.java ---------------------------------------------------------------------- diff --git a/core-job/src/main/java/org/apache/kylin/job/constant/ExecutableConstants.java b/core-job/src/main/java/org/apache/kylin/job/constant/ExecutableConstants.java index cec2e5d..4ae3add 100644 --- a/core-job/src/main/java/org/apache/kylin/job/constant/ExecutableConstants.java +++ b/core-job/src/main/java/org/apache/kylin/job/constant/ExecutableConstants.java @@ -37,7 +37,6 @@ public final class ExecutableConstants { public static final String STEP_NAME_BUILD_DICTIONARY = "Build Dimension Dictionary"; public static final String STEP_NAME_CREATE_FLAT_HIVE_TABLE = "Create Intermediate Flat Hive Table"; public static final String STEP_NAME_MATERIALIZE_HIVE_VIEW_IN_LOOKUP = "Materialize Hive View in Lookup Tables"; - public static final String STEP_NAME_COUNT_HIVE_TABLE = "Count Source Table"; public static final String STEP_NAME_FACT_DISTINCT_COLUMNS = "Extract Fact Table Distinct Columns"; public static final String STEP_NAME_BUILD_BASE_CUBOID = "Build Base Cuboid Data"; public static final String STEP_NAME_BUILD_IN_MEM_CUBE = "Build Cube"; @@ -55,9 +54,6 @@ public final class ExecutableConstants { public static final String STEP_NAME_KAFKA_CLEANUP = "Kafka Intermediate File Cleanup"; public static final String STEP_NAME_GARBAGE_COLLECTION = "Garbage Collection"; public static final String STEP_NAME_GARBAGE_COLLECTION_HDFS = "Garbage Collection on HDFS"; - public static final String STEP_NAME_BUILD_II = "Build Inverted Index"; - public static final String STEP_NAME_CONVERT_II_TO_HFILE = "Convert Inverted Index Data to HFile"; - public static final String STEP_NAME_UPDATE_II_INFO = "Update Inverted Index Info"; public static final String STEP_NAME_REDISTRIBUTE_FLAT_HIVE_TABLE = "Redistribute Flat Hive Table"; public static final String NOTIFY_EMAIL_TEMPLATE = "<div><b>Build Result of Job ${job_name}</b><pre><ul>" + "<li>Build Result: <b>${result}</b></li>" + "<li>Job Engine: ${job_engine}</li>" + "<li>Env: ${env_name}</li>" + "<li>Project: ${project_name}</li>" + "<li>Cube Name: ${cube_name}</li>" + "<li>Source Records Count: ${source_records_count}</li>" + "<li>Start Time: ${start_time}</li>" + "<li>Duration: ${duration}</li>" + "<li>MR Waiting: ${mr_waiting}</li>" + "<li>Last Update Time: ${last_update_time}</li>" + "<li>Submitter: ${submitter}</li>" + "<li>Error Log: ${error_log}</li>" + "</ul></pre><div/>"; } http://git-wip-us.apache.org/repos/asf/kylin/blob/4d1676a6/server-base/src/main/java/org/apache/kylin/rest/service/AdminService.java ---------------------------------------------------------------------- diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/AdminService.java b/server-base/src/main/java/org/apache/kylin/rest/service/AdminService.java index ace0388..a02804e 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/service/AdminService.java +++ b/server-base/src/main/java/org/apache/kylin/rest/service/AdminService.java @@ -22,10 +22,12 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Map; import java.util.Properties; +import java.util.TreeMap; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.kylin.common.KylinConfig; +import org.apache.kylin.common.util.OrderedProperties; import org.apache.kylin.rest.constant.Constant; import org.apache.kylin.rest.exception.InternalErrorException; import org.apache.kylin.tool.StorageCleanupJob; @@ -49,7 +51,7 @@ public class AdminService extends BasicService { @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN) public String getEnv() { PropertiesConfiguration tempConfig = new PropertiesConfiguration(); - + OrderedProperties orderedProperties = new OrderedProperties(new TreeMap<String, String>()); // Add Java Env try { @@ -59,14 +61,18 @@ public class AdminService extends BasicService { Map<String, String> env = System.getenv(); for (Map.Entry<String, String> entry : env.entrySet()) { - tempConfig.addProperty(entry.getKey(), entry.getValue()); + orderedProperties.setProperty(entry.getKey(), entry.getValue()); } // properties - Properties proterties = System.getProperties(); + Properties properties = System.getProperties(); - for (Map.Entry<Object, Object> entry : proterties.entrySet()) { - tempConfig.setProperty((String) entry.getKey(), entry.getValue()); + for (Map.Entry<Object, Object> entry : properties.entrySet()) { + orderedProperties.setProperty((String) entry.getKey(), (String) entry.getValue()); + } + + for (Map.Entry<String, String> entry : orderedProperties.entrySet()) { + tempConfig.addProperty(entry.getKey(), entry.getValue()); } // do save