blob: d23a091784443e29c4f4899a56850c5f2d26be33 [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.iotdb.it.env.cluster;
import org.apache.iotdb.it.framework.IoTDBTestLogger;
import org.apache.iotdb.tsfile.utils.Pair;
import org.apache.commons.lang3.SystemUtils;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import static org.apache.iotdb.consensus.ConsensusFactory.IOT_CONSENSUS;
import static org.apache.iotdb.consensus.ConsensusFactory.RATIS_CONSENSUS;
import static org.apache.iotdb.consensus.ConsensusFactory.SIMPLE_CONSENSUS;
import static org.apache.iotdb.db.utils.DateTimeUtils.convertLongToDate;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.CLUSTER_CONFIGURATIONS;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.DEFAULT_CONFIG_NODE_NUM;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.DEFAULT_DATA_NODE_NUM;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.DELIMITER;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.DIR_TIME_REPLACEMENT;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.HIGH_PERFORMANCE_MODE;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.HIGH_PERFORMANCE_MODE_CONFIG_NODE_NUM;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.HIGH_PERFORMANCE_MODE_DATA_NODE_NUM;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.IOT_CONSENSUS_STR;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.LIGHT_WEIGHT_STANDALONE_MODE;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.LIGHT_WEIGHT_STANDALONE_MODE_CONFIG_NODE_NUM;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.LIGHT_WEIGHT_STANDALONE_MODE_DATA_NODE_NUM;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.LOCK_FILE_PATH;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.RATIS_CONSENSUS_STR;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.SCALABLE_SINGLE_NODE_MODE;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.SCALABLE_SINGLE_NODE_MODE_CONFIG_NODE_NUM;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.SCALABLE_SINGLE_NODE_MODE_DATA_NODE_NUM;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.SIMPLE_CONSENSUS_STR;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.STRONG_CONSISTENCY_CLUSTER_MODE;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.STRONG_CONSISTENCY_CLUSTER_MODE_CONFIG_NODE_NUM;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.STRONG_CONSISTENCY_CLUSTER_MODE_DATA_NODE_NUM;
import static org.apache.iotdb.it.env.cluster.ClusterConstant.USER_DIR;
public class EnvUtils {
public static int[] searchAvailablePorts() {
int length = 10;
while (true) {
int randomPortStart = 1000 + (int) (Math.random() * (1999 - 1000));
randomPortStart = randomPortStart * (length + 1) + 1;
String lockFilePath = getLockFilePath(randomPortStart);
File lockFile = new File(lockFilePath);
try {
// Lock the ports first to avoid to be occupied by other ForkedBooters during ports
// available detecting
if (!lockFile.createNewFile()) {
continue;
}
List<Integer> requiredPorts =
IntStream.rangeClosed(randomPortStart, randomPortStart + length)
.boxed()
.collect(Collectors.toList());
if (checkPortsAvailable(requiredPorts)) {
return requiredPorts.stream().mapToInt(Integer::intValue).toArray();
}
} catch (IOException e) {
// ignore
}
// Delete the lock file if the ports can't be used or some error happens
if (lockFile.exists() && !lockFile.delete()) {
IoTDBTestLogger.logger.error("Delete lockfile {} failed", lockFilePath);
}
}
}
private static boolean checkPortsAvailable(List<Integer> ports) {
String cmd = getSearchAvailablePortCmd(ports);
try {
Process proc = Runtime.getRuntime().exec(cmd);
return proc.waitFor() == 1;
} catch (IOException e) {
// ignore
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return false;
}
private static String getSearchAvailablePortCmd(List<Integer> ports) {
if (SystemUtils.IS_OS_WINDOWS) {
return getWindowsSearchPortCmd(ports);
}
return getUnixSearchPortCmd(ports);
}
private static String getWindowsSearchPortCmd(List<Integer> ports) {
String cmd = "netstat -aon -p tcp | findStr ";
return cmd
+ ports.stream().map(v -> "/C:'127.0.0.1:" + v + "'").collect(Collectors.joining(" "));
}
private static String getUnixSearchPortCmd(List<Integer> ports) {
String cmd = "lsof -iTCP -sTCP:LISTEN -P -n | awk '{print $9}' | grep -E ";
return cmd + ports.stream().map(String::valueOf).collect(Collectors.joining("|")) + "\"";
}
private static Pair<Integer, Integer> getClusterNodesNum(int index) {
String valueStr = System.getProperty(CLUSTER_CONFIGURATIONS);
if (valueStr == null) {
return null;
}
try {
switch (getValueOfIndex(valueStr, index)) {
case LIGHT_WEIGHT_STANDALONE_MODE:
return new Pair<>(
Integer.parseInt(System.getProperty(LIGHT_WEIGHT_STANDALONE_MODE_CONFIG_NODE_NUM)),
Integer.parseInt(System.getProperty(LIGHT_WEIGHT_STANDALONE_MODE_DATA_NODE_NUM)));
case SCALABLE_SINGLE_NODE_MODE:
return new Pair<>(
Integer.parseInt(System.getProperty(SCALABLE_SINGLE_NODE_MODE_CONFIG_NODE_NUM)),
Integer.parseInt(System.getProperty(SCALABLE_SINGLE_NODE_MODE_DATA_NODE_NUM)));
case HIGH_PERFORMANCE_MODE:
return new Pair<>(
Integer.parseInt(System.getProperty(HIGH_PERFORMANCE_MODE_CONFIG_NODE_NUM)),
Integer.parseInt(System.getProperty(HIGH_PERFORMANCE_MODE_DATA_NODE_NUM)));
case STRONG_CONSISTENCY_CLUSTER_MODE:
return new Pair<>(
Integer.parseInt(System.getProperty(STRONG_CONSISTENCY_CLUSTER_MODE_CONFIG_NODE_NUM)),
Integer.parseInt(System.getProperty(STRONG_CONSISTENCY_CLUSTER_MODE_DATA_NODE_NUM)));
default:
// Print nothing to avoid polluting test outputs
return null;
}
} catch (NumberFormatException ignore) {
return null;
}
}
public static String getLockFilePath(int port) {
return LOCK_FILE_PATH + port;
}
public static Pair<Integer, Integer> getNodeNum() {
Pair<Integer, Integer> nodesNum = getClusterNodesNum(0);
if (nodesNum != null) {
return nodesNum;
}
return new Pair<>(
getIntFromSysVar(DEFAULT_CONFIG_NODE_NUM, 1, 0),
getIntFromSysVar(DEFAULT_DATA_NODE_NUM, 3, 0));
}
public static Pair<Integer, Integer> getNodeNum(int index) {
Pair<Integer, Integer> nodesNum = getClusterNodesNum(index);
if (nodesNum != null) {
return nodesNum;
}
return new Pair<>(
getIntFromSysVar(DEFAULT_CONFIG_NODE_NUM, 1, index),
getIntFromSysVar(DEFAULT_DATA_NODE_NUM, 3, index));
}
public static String getFilePathFromSysVar(String key, int index) {
String valueStr = System.getProperty(key);
if (valueStr == null) {
return null;
}
return System.getProperty(USER_DIR) + getValueOfIndex(valueStr, index);
}
public static int getIntFromSysVar(String key, int defaultValue, int index) {
String valueStr = System.getProperty(key);
if (valueStr == null) {
return defaultValue;
}
String value = getValueOfIndex(valueStr, index);
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid property value: " + value + " of key " + key);
}
}
public static String getValueOfIndex(String valueStr, int index) {
String[] values = valueStr.split(DELIMITER);
return index <= values.length - 1 ? values[index] : values[values.length - 1];
}
public static String getTimeForLogDirectory(long startTime) {
return convertLongToDate(startTime, "ms").replace(":", DIR_TIME_REPLACEMENT);
}
public static String fromConsensusFullNameToAbbr(String consensus) {
switch (consensus) {
case SIMPLE_CONSENSUS:
return SIMPLE_CONSENSUS_STR;
case RATIS_CONSENSUS:
return RATIS_CONSENSUS_STR;
case IOT_CONSENSUS:
return IOT_CONSENSUS_STR;
default:
throw new IllegalArgumentException("Unknown consensus type: " + consensus);
}
}
public static String fromConsensusAbbrToFullName(String consensus) {
switch (consensus) {
case SIMPLE_CONSENSUS_STR:
return SIMPLE_CONSENSUS;
case RATIS_CONSENSUS_STR:
return RATIS_CONSENSUS;
case IOT_CONSENSUS_STR:
return IOT_CONSENSUS;
default:
throw new IllegalArgumentException("Unknown consensus type: " + consensus);
}
}
private EnvUtils() {
throw new IllegalStateException("Utility class");
}
}