/** * Copyright (C) 2014-2016 LinkedIn Corp. (pinot-core@linkedin.com) * * 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 com.linkedin.pinot.controller; import com.linkedin.pinot.common.protocols.SegmentCompletionProtocol; import com.linkedin.pinot.common.utils.StringUtil; import java.io.File; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.PropertiesConfiguration; public class ControllerConf extends PropertiesConfiguration { private static final String CONTROLLER_VIP_HOST = "controller.vip.host"; private static final String CONTROLLER_VIP_PORT = "controller.vip.port"; private static final String CONTROLLER_VIP_PROTOCOL = "controller.vip.protocol"; private static final String CONTROLLER_HOST = "controller.host"; private static final String CONTROLLER_PORT = "controller.port"; private static final String DATA_DIR = "controller.data.dir"; private static final String ZK_STR = "controller.zk.str"; private static final String UPDATE_SEGMENT_STATE_MODEL = "controller.update_segment_state_model"; // boolean: Update the statemodel on boot? private static final String HELIX_CLUSTER_NAME = "controller.helix.cluster.name"; private static final String CLUSTER_TENANT_ISOLATION_ENABLE = "cluster.tenant.isolation.enable"; private static final String CONSOLE_WEBAPP_ROOT_PATH = "controller.query.console"; private static final String EXTERNAL_VIEW_ONLINE_TO_OFFLINE_TIMEOUT = "controller.upload.onlineToOfflineTimeout"; private static final String RETENTION_MANAGER_FREQUENCY_IN_SECONDS = "controller.retention.frequencyInSeconds"; private static final String VALIDATION_MANAGER_FREQUENCY_IN_SECONDS = "controller.validation.frequencyInSeconds"; private static final String STATUS_CHECKER_FREQUENCY_IN_SECONDS = "controller.statuschecker.frequencyInSeconds"; private static final String STATUS_CHECKER_WAIT_FOR_PUSH_TIME_IN_SECONDS = "controller.statuschecker.waitForPushTimeInSeconds"; private static final String SERVER_ADMIN_REQUEST_TIMEOUT_SECONDS = "server.request.timeoutSeconds"; private static final String SEGMENT_COMMIT_TIMEOUT_SECONDS = "controller.realtime.segment.commit.timeoutSeconds"; private static final String DELETED_SEGMENTS_RETENTION_IN_DAYS = "controller.deleted.segments.retentionInDays"; private static final String TASK_MANAGER_FREQUENCY_IN_SECONDS = "controller.task.frequencyInSeconds"; private static final String TABLE_MIN_REPLICAS = "table.minReplicas"; private static final int DEFAULT_RETENTION_CONTROLLER_FREQUENCY_IN_SECONDS = 6 * 60 * 60; // 6 Hours. private static final int DEFAULT_VALIDATION_CONTROLLER_FREQUENCY_IN_SECONDS = 60 * 60; // 1 Hour. private static final int DEFAULT_STATUS_CONTROLLER_FREQUENCY_IN_SECONDS = 5 * 60; // 5 minutes private static final int DEFAULT_STATUS_CONTROLLER_WAIT_FOR_PUSH_TIME_IN_SECONDS = 10 * 60; // 10 minutes private static final long DEFAULT_EXTERNAL_VIEW_ONLINE_TO_OFFLINE_TIMEOUT_MILLIS = 120_000L; // 2 minutes private static final int DEFAULT_SERVER_ADMIN_REQUEST_TIMEOUT_SECONDS = 30; private static final int DEFAULT_DELETED_SEGMENTS_RETENTION_IN_DAYS = 7; private static final int DEFAULT_TASK_MANAGER_FREQUENCY_IN_SECONDS = -1; // Disabled private static final int DEFAULT_TABLE_MIN_REPLICAS = 1; public ControllerConf(File file) throws ConfigurationException { super(file); } public ControllerConf() { super(); } public static String constructDownloadUrl(String tableName, String segmentName, String vip) { try { return StringUtil.join("/", vip, "segments", tableName, URLEncoder.encode(segmentName, "UTF-8")); } catch (UnsupportedEncodingException e) { // Shouldn't happen throw new AssertionError("UTF-8 encoding should always be supported", e); } } public void setQueryConsolePath(String path) { setProperty(CONSOLE_WEBAPP_ROOT_PATH, path); } public String getQueryConsole() { if (containsKey(CONSOLE_WEBAPP_ROOT_PATH)) { return (String) getProperty(CONSOLE_WEBAPP_ROOT_PATH); } return ControllerConf.class.getClassLoader().getResource("webapp").toExternalForm(); } public void setHelixClusterName(String clusterName) { setProperty(HELIX_CLUSTER_NAME, clusterName); } public void setControllerHost(String host) { setProperty(CONTROLLER_HOST, host); } public void setControllerVipHost(String vipHost) { setProperty(CONTROLLER_VIP_HOST, vipHost); } public void setControllerVipPort(String vipPort) { setProperty(CONTROLLER_VIP_PORT, vipPort); } public void setControllerVipProtocol(String vipProtocol) { setProperty(CONTROLLER_VIP_PROTOCOL, vipProtocol); } public void setControllerPort(String port) { setProperty(CONTROLLER_PORT, port); } public void setDataDir(String dataDir) { setProperty(DATA_DIR, dataDir); } public void setRealtimeSegmentCommitTimeoutSeconds(int timeoutSec) { setProperty(SEGMENT_COMMIT_TIMEOUT_SECONDS, Integer.toString(timeoutSec)); } public void setUpdateSegmentStateModel(String updateStateModel) { setProperty(UPDATE_SEGMENT_STATE_MODEL, updateStateModel); } public void setZkStr(String zkStr) { setProperty(ZK_STR, zkStr); } public String getHelixClusterName() { return (String) getProperty(HELIX_CLUSTER_NAME); } public String getControllerHost() { return (String) getProperty(CONTROLLER_HOST); } public String getControllerPort() { return (String) getProperty(CONTROLLER_PORT); } public String getDataDir() { return (String) getProperty(DATA_DIR); } public int getSegmentCommitTimeoutSeconds() { if (containsKey(SEGMENT_COMMIT_TIMEOUT_SECONDS)) { return Integer.parseInt((String)getProperty(SEGMENT_COMMIT_TIMEOUT_SECONDS)); } return SegmentCompletionProtocol.getDefaultMaxSegmentCommitTimeSeconds(); } public boolean isUpdateSegmentStateModel() { if (containsKey(UPDATE_SEGMENT_STATE_MODEL)) { return Boolean.parseBoolean(getProperty(UPDATE_SEGMENT_STATE_MODEL).toString()); } return false; // Default is to leave the statemodel untouched. } public String generateVipUrl() { return getControllerVipProtocol() + "://" + getControllerVipHost() + ":" + getControllerVipPort(); } public String getZkStr() { Object zkAddressObj = getProperty(ZK_STR); // The set method converted comma separated string into ArrayList, so need to convert back to String here. if (zkAddressObj instanceof ArrayList) { List<String> zkAddressList = (ArrayList<String>) zkAddressObj; String[] zkAddress = zkAddressList.toArray(new String[0]); return StringUtil.join(",", zkAddress); } else if (zkAddressObj instanceof String) { return (String) zkAddressObj; } else { throw new RuntimeException("Unexpected data type for zkAddress PropertiesConfiguration, expecting String but got " + zkAddressObj.getClass().getName()); } } @Override public String toString() { return super.toString(); } public String getControllerVipHost() { if (containsKey(CONTROLLER_VIP_HOST) && ((String) getProperty(CONTROLLER_VIP_HOST)).length() > 0) { return (String) getProperty(CONTROLLER_VIP_HOST); } return (String) getProperty(CONTROLLER_HOST); } public String getControllerVipPort() { if (containsKey(CONTROLLER_VIP_PORT) && ((String) getProperty(CONTROLLER_VIP_PORT)).length() > 0) { return (String) getProperty(CONTROLLER_VIP_PORT); } return (String) getProperty(CONTROLLER_PORT); } public String getControllerVipProtocol() { if (containsKey(CONTROLLER_VIP_PROTOCOL) && ((String) getProperty(CONTROLLER_VIP_PROTOCOL)).equals("https")) { return "https"; } return "http"; } public int getRetentionControllerFrequencyInSeconds() { if (containsKey(RETENTION_MANAGER_FREQUENCY_IN_SECONDS)) { return Integer.parseInt((String) getProperty(RETENTION_MANAGER_FREQUENCY_IN_SECONDS)); } return DEFAULT_RETENTION_CONTROLLER_FREQUENCY_IN_SECONDS; } public void setRetentionControllerFrequencyInSeconds(int retentionFrequencyInSeconds) { setProperty(RETENTION_MANAGER_FREQUENCY_IN_SECONDS, Integer.toString(retentionFrequencyInSeconds)); } public int getValidationControllerFrequencyInSeconds() { if (containsKey(VALIDATION_MANAGER_FREQUENCY_IN_SECONDS)) { return Integer.parseInt((String) getProperty(VALIDATION_MANAGER_FREQUENCY_IN_SECONDS)); } return DEFAULT_VALIDATION_CONTROLLER_FREQUENCY_IN_SECONDS; } public void setValidationControllerFrequencyInSeconds(int validationFrequencyInSeconds) { setProperty(VALIDATION_MANAGER_FREQUENCY_IN_SECONDS, Integer.toString(validationFrequencyInSeconds)); } public int getStatusCheckerFrequencyInSeconds() { if (containsKey(STATUS_CHECKER_FREQUENCY_IN_SECONDS)) { return Integer.parseInt((String) getProperty(STATUS_CHECKER_FREQUENCY_IN_SECONDS)); } return DEFAULT_STATUS_CONTROLLER_FREQUENCY_IN_SECONDS; } public void setStatusCheckerFrequencyInSeconds(int statusCheckerFrequencyInSeconds) { setProperty(STATUS_CHECKER_FREQUENCY_IN_SECONDS, Integer.toString(statusCheckerFrequencyInSeconds)); } public int getStatusCheckerWaitForPushTimeInSeconds() { if (containsKey(STATUS_CHECKER_WAIT_FOR_PUSH_TIME_IN_SECONDS)) { return Integer.parseInt((String) getProperty(STATUS_CHECKER_WAIT_FOR_PUSH_TIME_IN_SECONDS)); } return DEFAULT_STATUS_CONTROLLER_WAIT_FOR_PUSH_TIME_IN_SECONDS; } public void setStatusCheckerWaitForPushTimeInSeconds(int statusCheckerWaitForPushTimeInSeconds) { setProperty(STATUS_CHECKER_WAIT_FOR_PUSH_TIME_IN_SECONDS, Integer.toString(statusCheckerWaitForPushTimeInSeconds)); } public long getExternalViewOnlineToOfflineTimeout() { if (containsKey(EXTERNAL_VIEW_ONLINE_TO_OFFLINE_TIMEOUT)) { return Integer.parseInt((String) getProperty(EXTERNAL_VIEW_ONLINE_TO_OFFLINE_TIMEOUT)); } return DEFAULT_EXTERNAL_VIEW_ONLINE_TO_OFFLINE_TIMEOUT_MILLIS; } public void setExternalViewOnlineToOfflineTimeout(long timeout) { setProperty(EXTERNAL_VIEW_ONLINE_TO_OFFLINE_TIMEOUT, timeout); } public boolean tenantIsolationEnabled() { if (containsKey(CLUSTER_TENANT_ISOLATION_ENABLE)) { return Boolean.parseBoolean(getProperty(CLUSTER_TENANT_ISOLATION_ENABLE).toString()); } return true; } public void setTenantIsolationEnabled(boolean isSingleTenant) { setProperty(CLUSTER_TENANT_ISOLATION_ENABLE, isSingleTenant); } public void setServerAdminRequestTimeoutSeconds(int timeoutSeconds) { setProperty(SERVER_ADMIN_REQUEST_TIMEOUT_SECONDS, timeoutSeconds); } public int getServerAdminRequestTimeoutSeconds() { return getInt(SERVER_ADMIN_REQUEST_TIMEOUT_SECONDS, DEFAULT_SERVER_ADMIN_REQUEST_TIMEOUT_SECONDS); } public int getDeletedSegmentsRetentionInDays() { return getInt(DELETED_SEGMENTS_RETENTION_IN_DAYS, DEFAULT_DELETED_SEGMENTS_RETENTION_IN_DAYS); } public void setDeletedSegmentsRetentionInDays(int retentionInDays) { setProperty(DELETED_SEGMENTS_RETENTION_IN_DAYS, retentionInDays); } public int getTaskManagerFrequencyInSeconds() { return getInt(TASK_MANAGER_FREQUENCY_IN_SECONDS, DEFAULT_TASK_MANAGER_FREQUENCY_IN_SECONDS); } public void setTaskManagerFrequencyInSeconds(int frequencyInSeconds) { setProperty(TASK_MANAGER_FREQUENCY_IN_SECONDS, Integer.toString(frequencyInSeconds)); } public int getDefaultTableMinReplicas() { return getInt(TABLE_MIN_REPLICAS, DEFAULT_TABLE_MIN_REPLICAS); } public void setTableMinReplicas(int minReplicas) { setProperty(TABLE_MIN_REPLICAS, minReplicas); } }