This is an automated email from the ASF dual-hosted git repository.
haonan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new e825af4aade feature add iotdb backup (#12365)
e825af4aade is described below
commit e825af4aade4370a68c7c4a84918f3d3ca30bb7f
Author: CloudWise-Lukemiao <[email protected]>
AuthorDate: Tue Apr 23 15:00:16 2024 +0800
feature add iotdb backup (#12365)
Co-authored-by: luke.miao <[email protected]>
---
.../cli/src/assembly/resources/tools/backup.bat | 118 +++
.../cli/src/assembly/resources/tools/backup.sh | 128 +++
.../org/apache/iotdb/tool/IoTDBDataBackTool.java | 985 +++++++++++++++++++++
3 files changed, 1231 insertions(+)
diff --git a/iotdb-client/cli/src/assembly/resources/tools/backup.bat
b/iotdb-client/cli/src/assembly/resources/tools/backup.bat
new file mode 100644
index 00000000000..c91b426a34e
--- /dev/null
+++ b/iotdb-client/cli/src/assembly/resources/tools/backup.bat
@@ -0,0 +1,118 @@
+@REM
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM
+
+@echo off
+setlocal enabledelayedexpansion
+
+if "%OS%" == "Windows_NT" setlocal
+
+pushd %~dp0..
+if NOT DEFINED IOTDB_HOME set IOTDB_HOME=%CD%
+popd
+
+if NOT DEFINED JAVA_HOME goto :err
+
+set JAVA_OPTS=-ea^
+ -DIOTDB_HOME=%IOTDB_HOME%
+
+SET IOTDB_CONF=%IOTDB_HOME%\conf
+IF EXIST "%IOTDB_CONF%\datanode-env.bat" (
+ CALL "%IOTDB_CONF%\datanode-env.bat" > nul 2>&1
+) ELSE (
+ echo Can't find datanode-env.bat
+)
+
+IF EXIST "%IOTDB_CONF%\iotdb-datanode.properties" (
+ for /f "eol=# tokens=2 delims==" %%i in ('findstr /i "^dn_rpc_port"
+ %IOTDB_CONF%\iotdb-datanode.properties') do (
+ set dn_rpc_port=%%i
+ )
+) ELSE (
+ set dn_rpc_port=6667
+)
+
+IF EXIST "%IOTDB_CONF%\iotdb-confignode.properties" (
+ for /f "eol=# tokens=2 delims==" %%i in ('findstr /i "^cn_internal_port"
+ %IOTDB_CONF%\iotdb-confignode.properties') do (
+ set cn_internal_port=%%i
+ )
+) ELSE (
+ set cn_internal_port=10710
+)
+
+set "local_iotdb_occupied_ports="
+set "operation_dirs="
+set dn_rpc_port_occupied=0
+set cn_internal_port_occupied=0
+
+for /f "tokens=1,3,7 delims=: " %%i in ('netstat /ano') do (
+ if %%i==TCP (
+ if %%j==%dn_rpc_port% (
+ if !dn_rpc_port_occupied!==0 (
+ set spid=%%k
+ call :checkIfIOTDBProcess !spid! is_iotdb
+ if !is_iotdb!==1 (
+ set local_iotdb_occupied_ports=%dn_rpc_port%
!local_iotdb_occupied_ports!
+ )
+ )
+
+ ) else if %%j==%cn_internal_port% (
+ if !cn_internal_port_occupied!==0 (
+ set spid=%%k
+ call :checkIfIOTDBProcess !spid! is_iotdb
+ if !is_iotdb!==1 (
+ set local_iotdb_occupied_ports=%cn_internal_port%
!local_iotdb_occupied_ports!
+ )
+ )
+ )
+ )
+)
+
+if defined local_iotdb_occupied_ports (
+ goto :checkFail
+)
+
+set CLASSPATH=%CLASSPATH%;%IOTDB_HOME%\lib\*
+if NOT DEFINED MAIN_CLASS set
MAIN_CLASS=org.apache.iotdb.tool.IoTDBDataBackTool
+
+"%JAVA_HOME%\bin\java" -DIOTDB_HOME=!IOTDB_HOME! !JAVA_OPTS! -cp !CLASSPATH!
!MAIN_CLASS! %*
+pause
+exit /b
+
+:checkIfIOTDBProcess
+setlocal
+
+set "pid_to_check=%~1"
+set "is_iotdb=0"
+
+for /f "usebackq tokens=*" %%i in (`wmic process where
"ProcessId=%pid_to_check%" get CommandLine /format:list ^| findstr
/c:"CommandLine="`) do (
+ set command_line=%%i
+)
+echo %command_line% | findstr /i /c:"iotdb" >nul && set is_iotdb=1
+endlocal & set "is_iotdb=%is_iotdb%"
+exit /b
+
+:err
+echo JAVA_HOME environment variable must be set!
+set ret_code=1
+exit /b
+
+:checkFail
+echo Please stop IoTDB
+exit /b
\ No newline at end of file
diff --git a/iotdb-client/cli/src/assembly/resources/tools/backup.sh
b/iotdb-client/cli/src/assembly/resources/tools/backup.sh
new file mode 100755
index 00000000000..56cf5d2c998
--- /dev/null
+++ b/iotdb-client/cli/src/assembly/resources/tools/backup.sh
@@ -0,0 +1,128 @@
+#!/bin/bash
+#
+# 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.
+#
+
+echo ------------------------------------------
+echo Starting IoTDB Client Data Back Script
+echo ------------------------------------------
+
+
+if [ -z "${IOTDB_INCLUDE}" ]; then
+ #do nothing
+ :
+elif [ -r "$IOTDB_INCLUDE" ]; then
+ . "$IOTDB_INCLUDE"
+fi
+
+if [ -z "${IOTDB_HOME}" ]; then
+ export IOTDB_HOME="$(cd "`dirname "$0"`"/..; pwd)"
+fi
+
+if [ -n "$JAVA_HOME" ]; then
+ for java in "$JAVA_HOME"/bin/amd64/java "$JAVA_HOME"/bin/java; do
+ if [ -x "$java" ]; then
+ JAVA="$java"
+ break
+ fi
+ done
+else
+ JAVA=java
+fi
+
+if [ -z $JAVA ] ; then
+ echo Unable to find java executable. Check JAVA_HOME and PATH environment
variables. > /dev/stderr
+ exit 1;
+fi
+
+datanodeclassname=org.apache.iotdb.db.service.DataNode
+
+confignodeclassname=org.apache.iotdb.db.service.ConfigNode
+
+check_tool_env() {
+ if ! type lsof > /dev/null 2>&1 ; then
+ echo ""
+ echo " Warning: No tool 'lsof', Please install it."
+ echo " Note: Some checking function need 'lsof'."
+ echo ""
+ return 1
+ else
+ return 0
+ fi
+}
+
+get_properties_value() {
+ local file_name=$1
+ local property_name=$2
+ local default_value=$3
+ local property_value=$(sed "/^${property_name}=/!d;s/.*=//"
"${IOTDB_HOME}/conf/${file_name}.properties")
+ if [ -z "$property_value" ]; then
+ property_value="$default_value"
+ fi
+ echo "$property_value"
+}
+iotdb_listening_ports=()
+check_running_process() {
+ DATANODE="iotdb-datanode"
+ CONFIGNODE="iotdb-confignode"
+ dn_rpc_port=$(get_properties_value $DATANODE "dn_rpc_port" "6667")
+ cn_internal_port=$(get_properties_value $CONFIGNODE "cn_internal_port"
"10710")
+ local_ports+=("$dn_rpc_port")
+ local_ports+=("$cn_internal_port")
+ for port in "${local_ports[@]}"; do
+ # Check if lsof command is available
+ if command -v lsof >/dev/null 2>&1; then
+ listening=$(lsof -i :$port -sTCP:LISTEN -P -n | grep LISTEN)
+ if [ -n "$listening" ]; then
+ process_command=$(echo "$listening" | awk '{print $2}')
+ iotdb_check=$(ps -p "$process_command" -o args= | grep "iotdb")
+ if [ -n "$iotdb_check" ]; then
+ iotdb_listening_ports+=("$port ")
+ fi
+ fi
+ elif command -v netstat >/dev/null 2>&1; then
+ listening=$(netstat -tln | awk '{print $4}' | grep ":$port$")
+ if [ -n "$listening" ]; then
+ process_command=$(echo "$listening" | awk '{print $2}')
+ iotdb_check=$(ps -p "$process_command" -o args= | grep "iotdb")
+ if [ -n "$iotdb_check" ]; then
+ iotdb_listening_ports+=("$port ")
+ fi
+ fi
+ else
+ echo "Error: Unable to detect port occupation. Please install 'lsof'
or 'netstat' command."
+ exit 1
+ fi
+ done
+ if [ ${#iotdb_listening_ports[@]} -gt 0 ]; then
+ echo " Please stop IoTDB" >&2
+ echo " Exit..." >&2
+ echo ""
+ exit 1
+ fi
+}
+
+check_running_process
+
+for f in ${IOTDB_HOME}/lib/*.jar; do
+ CLASSPATH=${CLASSPATH}":"$f
+done
+
+MAIN_CLASS=org.apache.iotdb.tool.IoTDBDataBackTool
+
+"$JAVA" -DIOTDB_HOME=${IOTDB_HOME} -cp "$CLASSPATH" "$MAIN_CLASS" "$@"
diff --git
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/IoTDBDataBackTool.java
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/IoTDBDataBackTool.java
new file mode 100644
index 00000000000..19388312050
--- /dev/null
+++
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/IoTDBDataBackTool.java
@@ -0,0 +1,985 @@
+/*
+ * 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.tool;
+
+import org.apache.iotdb.commons.conf.IoTDBConstant;
+import org.apache.iotdb.db.conf.IoTDBConfig;
+import org.apache.iotdb.db.conf.IoTDBDescriptor;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class IoTDBDataBackTool {
+ static Map<String, String> mm = new HashMap<>();
+ static Map<String, String> cpmm = new HashMap<>();
+ static String type = "";
+ static String nodeTypeParam = "";
+
+ static String targetDirParam = "";
+ static String targetDataDirParam = "";
+ static String targetWalDirParam = "";
+
+ static String DATA_NODE_CONF_NAME = IoTDBConfig.CONFIG_NAME;
+ static String CONFIG_NODE_CONF_NAME = "iotdb-confignode.properties";
+ static AtomicInteger fileCount = new AtomicInteger(0);
+ static AtomicInteger targetFileCount = new AtomicInteger(0);
+ static AtomicInteger processFileCount = new AtomicInteger(0);
+ static final String filename = "data.txt";
+
+ private static final Logger LOGGER =
LoggerFactory.getLogger(AbstractDataTool.class);
+
+ private static final IoTDBDescriptor ioTDBDescriptor =
IoTDBDescriptor.getInstance();
+ static String sourcePath = System.getProperty(IoTDBConstant.IOTDB_HOME,
null);
+ static String DEFAULT_DN_DATA_DIRS =
+ "data"
+ + File.separator
+ + IoTDBConstant.DN_ROLE
+ + File.separator
+ + IoTDBConstant.DATA_FOLDER_NAME;
+ static String DEFAULT_DN_SYSTEM_DIR =
+ "data"
+ + File.separator
+ + IoTDBConstant.DN_ROLE
+ + File.separator
+ + IoTDBConstant.SYSTEM_FOLDER_NAME;
+
+ static String DEFAULT_DN_CONSENSUS_DIR =
+ "data"
+ + File.separator
+ + IoTDBConstant.DN_ROLE
+ + File.separator
+ + IoTDBConstant.CONSENSUS_FOLDER_NAME;
+ static String DEFAULT_DN_WAL_DIRS =
+ "data"
+ + File.separator
+ + IoTDBConstant.DN_ROLE
+ + File.separator
+ + IoTDBConstant.WAL_FOLDER_NAME;
+
+ static String DEFAULT_DN_TRACING_DIR =
+ "data" + File.separator + IoTDBConstant.DN_ROLE + File.separator +
"tracing";
+
+ static String DEFAULT_CN_SYSTEM_DIR =
+ "data"
+ + File.separator
+ + IoTDBConstant.CN_ROLE
+ + File.separator
+ + IoTDBConstant.SYSTEM_FOLDER_NAME;
+
+ static String DEFAULT_CN_CONSENSUS_DIR =
+ "data"
+ + File.separator
+ + IoTDBConstant.CN_ROLE
+ + File.separator
+ + IoTDBConstant.CONSENSUS_FOLDER_NAME;
+
+ private static void argsParse(String[] args) {
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].equalsIgnoreCase("-quick")) {
+ type = "quick";
+ } else if (args[i].equalsIgnoreCase("-node") && i + 1 < args.length) {
+ nodeTypeParam = args[i + 1];
+ } else if (args[i].equalsIgnoreCase("-targetdir") && i + 1 <
args.length) {
+ targetDirParam = args[i + 1];
+ } else if (args[i].equalsIgnoreCase("-targetdatadir") && i + 1 <
args.length) {
+ targetDataDirParam = args[i + 1];
+ } else if (args[i].equalsIgnoreCase("-targetwaldir") && i + 1 <
args.length) {
+ targetWalDirParam = args[i + 1];
+ }
+ }
+ }
+
+ public static boolean vaildParam(String dnDataDirs, String dnWalDirs) {
+ boolean isVaild = true;
+ if (type == null || type.trim().length() == 0 || !type.equals("quick")) {
+ if (targetDirParam.isEmpty()) {
+ LOGGER.error(" -targetdir cannot be empty, The backup folder must be
specified");
+ isVaild = false;
+ }
+
+ if (!targetDataDirParam.isEmpty()) {
+ if (!matchPattern(targetDataDirParam, dnDataDirs)) {
+ LOGGER.error(
+ "-targetdatadir parameter exception, the number of original
paths does not match the number of specified paths");
+ isVaild = false;
+ }
+ }
+
+ if (!targetWalDirParam.isEmpty()) {
+ if (!matchPattern(targetWalDirParam, dnWalDirs)) {
+ LOGGER.error(
+ "-targetwaldir parameter exception, the number of original paths
does not match the number of specified paths");
+ isVaild = false;
+ }
+ }
+ }
+ return isVaild;
+ }
+
+ public static void main(String[] args) {
+ argsParse(args);
+ File sourceDir = new File(sourcePath);
+ Properties dataProperties = getProperties(IoTDBConfig.CONFIG_NAME);
+ initDataNodeProperties(dataProperties);
+ Properties configProperties = getProperties(CONFIG_NODE_CONF_NAME);
+ initConfigNodeProperties(configProperties);
+
+ StringBuilder targetDirString = new StringBuilder();
+ Map<String, String> copyMap = new HashMap<>();
+ Map<String, String> dnDataDirsMap = new HashMap<>();
+ Map<String, String> cnMapProperties = new HashMap<>();
+ Map<String, String> dnMapProperties = new HashMap<>();
+ processFileCount.set(readFileData(filename));
+ if (type != null && type.equals("quick")) {
+ targetDirString
+ .append(sourceDir.getParent())
+ .append(File.separatorChar)
+ .append("iotdb_backup");
+ File targetDir = new File(targetDirString.toString());
+ if (!targetDir.exists()) {
+ targetDir.mkdirs();
+ } else {
+ LOGGER.error("The backup folder already exists:{}", targetDirString);
+ System.exit(0);
+ }
+
+ countConfigNodeFile(targetDirString.toString(), copyMap,
cnMapProperties);
+ countDataNodeFile(targetDirString.toString(), copyMap, dnDataDirsMap,
dnMapProperties);
+ countNodeBack(targetDirString.toString(), copyMap);
+ for (Map.Entry<String, String> entry : copyMap.entrySet()) {
+ countFiles(entry.getKey());
+ }
+ for (Map.Entry<String, String> entry : dnDataDirsMap.entrySet()) {
+ countFiles(entry.getKey());
+ }
+
+ ioTDBDataBack(copyMap, dnDataDirsMap);
+ propertiesFileUpdate(
+ targetDirString.toString()
+ + File.separatorChar
+ + "conf"
+ + File.separatorChar
+ + CONFIG_NODE_CONF_NAME,
+ cnMapProperties);
+ propertiesFileUpdate(
+ targetDirString.toString()
+ + File.separatorChar
+ + "conf"
+ + File.separatorChar
+ + DATA_NODE_CONF_NAME,
+ dnMapProperties);
+ } else {
+ if (targetDirParam != null && targetDirParam.length() > 0) {
+ targetDirString.append(targetDirParam);
+ File targetDir = new File(targetDirString.toString());
+ if (!targetDir.exists()) {
+ targetDir.mkdirs();
+ }
+ }
+
+ if (nodeTypeParam.equalsIgnoreCase("confignode")) {
+ countConfigNodeFile(targetDirString.toString(), copyMap,
cnMapProperties);
+ countNodeBack(targetDirString.toString(), copyMap);
+ for (Map.Entry<String, String> entry : copyMap.entrySet()) {
+ countFiles(entry.getKey());
+ }
+ ioTDBDataBack(copyMap, dnDataDirsMap);
+ propertiesFileUpdate(
+ targetDirString.toString()
+ + File.separatorChar
+ + "conf"
+ + File.separatorChar
+ + CONFIG_NODE_CONF_NAME,
+ cnMapProperties);
+ } else if (nodeTypeParam.equalsIgnoreCase("datanode")) {
+ countNodeBack(targetDirString.toString(), copyMap);
+ countDataNodeFile(targetDirString.toString(), copyMap, dnDataDirsMap,
dnMapProperties);
+ for (Map.Entry<String, String> entry : copyMap.entrySet()) {
+ countFiles(entry.getKey());
+ }
+ for (Map.Entry<String, String> entry : dnDataDirsMap.entrySet()) {
+ countFiles(entry.getKey());
+ }
+ ioTDBDataBack(copyMap, dnDataDirsMap);
+ propertiesFileUpdate(
+ targetDirString.toString()
+ + File.separatorChar
+ + "conf"
+ + File.separatorChar
+ + DATA_NODE_CONF_NAME,
+ dnMapProperties);
+ } else if (nodeTypeParam.equalsIgnoreCase("all") ||
nodeTypeParam.isEmpty()) {
+ countNodeBack(targetDirString.toString(), copyMap);
+ countConfigNodeFile(targetDirString.toString(), copyMap,
cnMapProperties);
+ countDataNodeFile(targetDirString.toString(), copyMap, dnDataDirsMap,
dnMapProperties);
+ for (Map.Entry<String, String> entry : copyMap.entrySet()) {
+ countFiles(entry.getKey());
+ }
+ for (Map.Entry<String, String> entry : dnDataDirsMap.entrySet()) {
+ countFiles(entry.getKey());
+ }
+ ioTDBDataBack(copyMap, dnDataDirsMap);
+ propertiesFileUpdate(
+ targetDirString.toString()
+ + File.separatorChar
+ + "conf"
+ + File.separatorChar
+ + CONFIG_NODE_CONF_NAME,
+ cnMapProperties);
+ propertiesFileUpdate(
+ targetDirString.toString()
+ + File.separatorChar
+ + "conf"
+ + File.separatorChar
+ + DATA_NODE_CONF_NAME,
+ dnMapProperties);
+ }
+ }
+ LOGGER.info("all operations are complete");
+ delFile(filename);
+ }
+
+ private static void ioTDBDataBack(
+ Map<String, String> copyMap, Map<String, String> dnDataDirsMap) {
+
+ for (Map.Entry<String, String> entry : copyMap.entrySet()) {
+ File file = new File(entry.getKey());
+ if (file.isDirectory()) {
+ compareAndcopyDirectory(file, new File(entry.getValue()));
+ } else {
+ if (file.exists()) {
+ File targetFile = new File(entry.getValue());
+ try {
+ Files.copy(file.toPath(), targetFile.toPath(),
StandardCopyOption.REPLACE_EXISTING);
+ targetFileCount.incrementAndGet();
+ } catch (IOException e) {
+ LOGGER.error("copy file error", e);
+ }
+ }
+ }
+ }
+
+ for (Map.Entry<String, String> entry : dnDataDirsMap.entrySet()) {
+ File file = new File(entry.getKey());
+ if (file.isDirectory()) {
+ compareAndLinkDirectory(file, new File(entry.getValue()));
+ } else {
+ if (file.exists()) {
+ File targetFile = new File(entry.getValue());
+ try {
+ Files.copy(file.toPath(), targetFile.toPath(),
StandardCopyOption.REPLACE_EXISTING);
+ targetFileCount.incrementAndGet();
+ } catch (IOException e) {
+ LOGGER.error("copy file error", e);
+ }
+ }
+ }
+ }
+ }
+
+ private static void countNodeBack(String targetDirString, Map<String,
String> copyMap) {
+ File sourceDir = new File(sourcePath);
+ Properties dataProperties = getProperties(IoTDBConfig.CONFIG_NAME);
+ initDataNodeProperties(dataProperties);
+ Properties configProperties = getProperties(CONFIG_NODE_CONF_NAME);
+ initConfigNodeProperties(configProperties);
+
+ copyMap.put(
+ sourceDir.getAbsolutePath() + File.separatorChar + ".env",
+ targetDirString + File.separatorChar + ".env");
+ copyMap.put(
+ sourceDir.getAbsolutePath() + File.separatorChar + "conf",
+ targetDirString + File.separatorChar + "conf");
+ copyMap.put(
+ sourceDir.getAbsolutePath() + File.separatorChar + "ext",
+ targetDirString + File.separatorChar + "ext");
+ copyMap.put(
+ sourceDir.getAbsolutePath() + File.separatorChar + "licenses",
+ targetDirString + File.separatorChar + "licenses");
+ copyMap.put(
+ sourceDir.getAbsolutePath() + File.separatorChar + "tools",
+ targetDirString + File.separatorChar + "tools");
+ copyMap.put(
+ sourceDir.getAbsolutePath() + File.separatorChar + "sbin",
+ targetDirString + File.separatorChar + "sbin");
+ copyMap.put(
+ sourceDir.getAbsolutePath() + File.separatorChar + "LICENSE",
+ targetDirString + File.separatorChar + "LICENSE");
+ copyMap.put(
+ sourceDir.getAbsolutePath() + File.separatorChar + "NOTICE",
+ targetDirString + File.separatorChar + "NOTICE");
+ copyMap.put(
+ sourceDir.getAbsolutePath() + File.separatorChar + "README.md",
+ targetDirString + File.separatorChar + "README.md");
+ copyMap.put(
+ sourceDir.getAbsolutePath() + File.separatorChar + "README_ZH.md",
+ targetDirString + File.separatorChar + "README_ZH.md");
+ copyMap.put(
+ sourceDir.getAbsolutePath() + File.separatorChar + File.separatorChar
+ "RELEASE_NOTES.md",
+ targetDirString + File.separatorChar + "RELEASE_NOTES.md");
+ copyMap.put(
+ sourceDir.getAbsolutePath() + File.separatorChar + "activation",
+ targetDirString + File.separatorChar + "activation");
+ copyMap.put(
+ sourceDir.getAbsolutePath() + File.separatorChar + "lib",
+ targetDirString + File.separatorChar + "lib");
+ }
+
+ private static void countDataNodeFile(
+ String targetDirString,
+ Map<String, String> copyMap,
+ Map<String, String> dnDataDirsMap,
+ Map<String, String> dnMapProperties) {
+ Properties dataProperties = getProperties(IoTDBConfig.CONFIG_NAME);
+ initDataNodeProperties(dataProperties);
+
+ String dnSystemDir = dataProperties.getProperty("dn_system_dir");
+ String dnConsensusDir = dataProperties.getProperty("dn_consensus_dir");
+
+ String dnTracingDir = dataProperties.getProperty("dn_tracing_dir");
+
+ String dnWalDirs = dataProperties.getProperty("dn_wal_dirs");
+ String dnDataDirs = dataProperties.getProperty("dn_data_dirs");
+
+ dnSystemDir = pathHandler(dnSystemDir);
+ dnConsensusDir = pathHandler(dnConsensusDir);
+ dnTracingDir = pathHandler(dnTracingDir);
+ dnWalDirs = pathHandler(dnWalDirs);
+ dnDataDirs = pathHandler(dnDataDirs);
+ String bakDnSystemDir = targetDirString + File.separatorChar +
DEFAULT_DN_SYSTEM_DIR;
+ String bakDnConsensusDir = targetDirString + File.separatorChar +
DEFAULT_DN_CONSENSUS_DIR;
+ String bakDnTracingDir = targetDirString + File.separatorChar +
DEFAULT_DN_TRACING_DIR;
+ String bakDnWalDirs = targetDirString + File.separatorChar +
DEFAULT_DN_WAL_DIRS;
+
+ if (type.equals("quick")) {
+ targetDataDirParam =
sourceDnDataDirsCoverTargetDnDataDirsHandler(dnDataDirs);
+ targetWalDirParam = sourceWalCoverTargetWalDirsHandler(dnWalDirs,
bakDnWalDirs);
+ }
+ if (targetWalDirParam.isEmpty()) {
+ targetWalDirParam = sourceWalCoverTargetWalDirsHandler(dnWalDirs,
bakDnWalDirs);
+ } else {
+ targetWalDirParam = getCreateDnDataPathString(dnWalDirs,
targetWalDirParam, "wal");
+ }
+ String targetDnDataDirs = "";
+ if (targetDataDirParam.isEmpty()) {
+ targetDnDataDirs =
sourceDnDataDirsCoverTargetDnDataDirsHandler(dnDataDirs);
+ } else {
+ targetDnDataDirs = getCreateDnDataPathString(dnDataDirs,
targetDataDirParam, "data");
+ }
+ // dnDataDirs = pathHandler(targetDataDirParam);
+ if (!vaildParam(targetDataDirParam, targetWalDirParam)) {
+ System.exit(0);
+ }
+
+ Map<String, String> dnSystemDirMap =
+ getCreatePathMapping(Objects.requireNonNull(dnSystemDir),
bakDnSystemDir, "system");
+ dnDataDirsMap.putAll(getCreatePathMapping(dnDataDirs, targetDnDataDirs,
"data"));
+ Map<String, String> dnConsensusDirMap =
+ getCreatePathMapping(
+ Objects.requireNonNull(dnConsensusDir), bakDnConsensusDir,
"consensus");
+ Map<String, String> dnTracingDirMap =
+ getCreatePathMapping(dnTracingDir, bakDnTracingDir, "tracing");
+ Map<String, String> dnWalDirsMap = getCreatePathMapping(dnWalDirs,
targetWalDirParam, "wal");
+ copyMap.putAll(dnSystemDirMap);
+ copyMap.putAll(dnConsensusDirMap);
+ copyMap.putAll(dnWalDirsMap);
+ copyMap.putAll(dnTracingDirMap);
+
+ dnMapProperties.put("dn_system_dir", bakDnSystemDir);
+ dnMapProperties.put("dn_data_dirs", targetDnDataDirs);
+ dnMapProperties.put("dn_wal_dirs", targetWalDirParam);
+ dnMapProperties.put("dn_tracing_dir", bakDnTracingDir);
+ dnMapProperties.put("dn_consensus_dir", bakDnConsensusDir);
+ }
+
+ private static void countConfigNodeFile(
+ String targetDirString, Map<String, String> copyMap, Map<String, String>
cnMapProperties) {
+ Properties configProperties = getProperties(CONFIG_NODE_CONF_NAME);
+ initConfigNodeProperties(configProperties);
+
+ String bakCnSystemDir = targetDirString + File.separatorChar +
DEFAULT_CN_SYSTEM_DIR;
+ String bakCnConsensusDir = targetDirString + File.separatorChar +
DEFAULT_CN_CONSENSUS_DIR;
+
+ if (!vaildParam(targetDataDirParam, targetWalDirParam)) {
+ System.exit(0);
+ }
+ String cnSystemDir = configProperties.getProperty("cn_system_dir");
+ String cnConsensusDir = configProperties.getProperty("cn_consensus_dir");
+ cnSystemDir = pathHandler(cnSystemDir);
+ cnConsensusDir = pathHandler(cnConsensusDir);
+ Map<String, String> cnSystemDirMap =
+ getCreatePathMapping(cnSystemDir, bakCnSystemDir, "system");
+ Map<String, String> cnConsensusDirMap =
+ getCreatePathMapping(cnConsensusDir, bakCnConsensusDir, "consensus");
+
+ copyMap.putAll(cnSystemDirMap);
+ copyMap.putAll(cnConsensusDirMap);
+
+ cnMapProperties.put("cn_system_dir", bakCnSystemDir);
+ cnMapProperties.put("cn_consensus_dir", bakCnConsensusDir);
+ }
+
+ private static String pathHandler(String pathsList) {
+ StringBuilder pathStrb = new StringBuilder();
+ String[] pathList = pathsList.split(";");
+ for (int t = 0; t < pathList.length; t++) {
+ String paths = pathList[t];
+ String[] dirList = paths.split(",");
+ for (int i = 0; i < dirList.length; i++) {
+ if (isRelativePath(dirList[i])) {
+ if (i == 0) {
+
pathStrb.append(sourcePath).append(File.separatorChar).append(dirList[i]);
+ } else {
+ pathStrb.append(",");
+
pathStrb.append(sourcePath).append(File.separatorChar).append(dirList[i]);
+ }
+ } else {
+ if (i == 0) {
+ pathStrb.append(dirList[i]);
+ } else {
+ pathStrb.append(",");
+ pathStrb.append(dirList[i]);
+ }
+ }
+ }
+ if (t < pathList.length - 1) {
+ pathStrb.append(";");
+ }
+ }
+
+ return pathStrb.toString();
+ }
+
+ private static boolean isRelativePath(String path) {
+ Path p = Paths.get(path);
+ return !p.isAbsolute();
+ }
+
+ public static String sourceDnDataDirsCoverTargetDnDataDirsHandler(String
dnDirs) {
+ String[] sourcePathsList = dnDirs.split(";");
+ StringBuilder targetDataDirSb = new StringBuilder();
+ for (int t = 0; t < sourcePathsList.length; t++) {
+ String sourcePaths = sourcePathsList[t];
+ String[] sourcePathList = sourcePaths.split(",");
+ StringBuilder subTargetDataDir = new StringBuilder();
+ for (int i = 0; i < sourcePathList.length; i++) {
+ String path = sourcePathList[i];
+ path = path + "_back";
+ if (i == sourcePathList.length - 1) {
+ subTargetDataDir.append(path);
+ } else {
+ subTargetDataDir.append(path).append(",");
+ }
+ }
+ if (t == sourcePathsList.length - 1) {
+ targetDataDirSb.append(subTargetDataDir);
+ } else {
+ targetDataDirSb.append(subTargetDataDir).append(";");
+ }
+ }
+ return targetDataDirSb.toString();
+ }
+
+ public static String sourceWalCoverTargetWalDirsHandler(String dnDirs,
String targetDirs) {
+ String[] sourcePathList = dnDirs.split(",");
+ StringBuilder subTargetDataDir = new StringBuilder();
+ for (int i = 0; i < sourcePathList.length; i++) {
+ if (i == sourcePathList.length - 1) {
+
subTargetDataDir.append(targetDirs).append(File.separatorChar).append("wal").append(i
+ 1);
+ } else {
+ subTargetDataDir
+ .append(targetDirs)
+ .append(File.separatorChar)
+ .append("wal")
+ .append(i + 1)
+ .append(",");
+ }
+ }
+ return subTargetDataDir.toString();
+ }
+
+ public static void propertiesFileUpdate(
+ String sourcePropertiesPath, Map<String, String> mapProperties) {
+ for (Map.Entry<String, String> entry : mapProperties.entrySet()) {
+ propertiesFileUpdate(sourcePropertiesPath, entry.getKey(),
entry.getValue());
+ }
+ }
+
+ public static String getCreateDnDataPathString(
+ String resourcePath, String targetPath, String dirType) {
+
+ String[] sourcePathsList = resourcePath.split(";");
+ String[] targetPathsList = targetPath.split(";");
+ StringBuilder pathStrb = new StringBuilder();
+ if (sourcePathsList.length != targetPathsList.length) {
+ int num = 1;
+ for (int i = 0; i < sourcePathsList.length; i++) {
+ String[] sourcePathArray = sourcePathsList[i].split(",");
+ for (int j = 0; j < sourcePathArray.length; j++) {
+ String newPath = targetPathsList[0];
+ if (sourcePathsList.length == 1 && targetPathsList.length == 1) {
+ newPath = newPath + File.separatorChar + dirType;
+ } else {
+ newPath = newPath + File.separatorChar + dirType + num;
+ }
+ pathStrb.append(newPath);
+ if (j < sourcePathArray.length - 1) {
+ pathStrb.append(",");
+ }
+ num++;
+ }
+ if (i < sourcePathsList.length - 1) {
+ pathStrb.append(";");
+ }
+ }
+ } else {
+ int num = 1;
+ for (int i = 0; i < sourcePathsList.length; i++) {
+ String[] sourcePathArray = sourcePathsList[i].split(",");
+ String[] targetPathArray = targetPathsList[i].split(",");
+ if (sourcePathArray.length != targetPathArray.length) {
+ if (targetPathArray.length == 1) {
+ for (int j = 0; j < sourcePathArray.length; j++) {
+ String newPath = "";
+ if (sourcePathsList.length == 1 && targetPathsList.length == 1) {
+ newPath = targetPathArray[0] + File.separatorChar + dirType;
+ } else {
+ newPath = targetPathArray[0] + File.separatorChar + dirType +
num;
+ }
+ pathStrb.append(newPath);
+ if (j < sourcePathArray.length - 1) {
+ pathStrb.append(",");
+ }
+ num++;
+ }
+ } else {
+ for (int j = 0; j < sourcePathArray.length; j++) {
+ pathStrb.append(targetPathArray[j]);
+ if (j < sourcePathArray.length - 1) {
+ pathStrb.append(",");
+ }
+ }
+ }
+ } else {
+ for (int j = 0; j < sourcePathArray.length; j++) {
+ pathStrb.append(targetPathArray[j]);
+ if (j < sourcePathArray.length - 1) {
+ pathStrb.append(",");
+ }
+ }
+ }
+ if (sourcePathsList.length > 1 && i < sourcePathsList.length - 1) {
+ pathStrb.append(";");
+ }
+ }
+ }
+
+ return pathStrb.toString();
+ }
+
+ public static Map<String, String> getCreatePathMapping(
+ String resourcePath, String targetPath, String dirType) {
+ Map<String, String> map = new HashMap<>();
+ String[] sourcePathsList = resourcePath.split(";");
+ String[] targetPathsList = targetPath.split(";");
+ if (sourcePathsList.length != targetPathsList.length) {
+ int num = 1;
+ for (int i = 0; i < sourcePathsList.length; i++) {
+ String[] sourcePathArray = sourcePathsList[i].split(",");
+ for (int j = 0; j < sourcePathArray.length; j++) {
+ String newPath = targetPathsList[0];
+ if (sourcePathsList.length == 1 && targetPathsList.length == 1) {
+ newPath = newPath + File.separatorChar + dirType;
+ } else {
+ newPath = newPath + File.separatorChar + dirType + num;
+ }
+ createDirectory(newPath);
+ map.put(sourcePathArray[j], newPath);
+ num++;
+ }
+ }
+ } else {
+ int num = 1;
+ for (int i = 0; i < sourcePathsList.length; i++) {
+ String[] sourcePathArray = sourcePathsList[i].split(",");
+ String[] targetPathArray = targetPathsList[i].split(",");
+ if (sourcePathArray.length != targetPathArray.length) {
+ if (targetPathArray.length == 1) {
+ for (int j = 0; j < sourcePathArray.length; j++) {
+ String newPath = "";
+ if (sourcePathsList.length == 1 && targetPathsList.length == 1) {
+ newPath = targetPathArray[0] + File.separatorChar + dirType;
+ } else {
+ newPath = targetPathArray[0] + File.separatorChar + dirType +
num;
+ }
+ createDirectory(newPath);
+ map.put(sourcePathArray[j], newPath);
+ num++;
+ }
+ } else {
+ for (int j = 0; j < sourcePathArray.length; j++) {
+ map.put(sourcePathArray[j], targetPathArray[j]);
+ }
+ }
+ } else {
+ for (int j = 0; j < sourcePathArray.length; j++) {
+ map.put(sourcePathArray[j], targetPathArray[j]);
+ }
+ }
+ }
+ }
+
+ return map;
+ }
+
+ public static boolean matchPattern(String input, String pattern) {
+ if (input.contains(";") && pattern.contains(";")) {
+ String[] inputDirs = input.split(";");
+ String[] patternDirs = pattern.split(";");
+ if (inputDirs.length != patternDirs.length) {
+ return false;
+ }
+ for (int i = 0; i < inputDirs.length; i++) {
+ String inputDir = inputDirs[i];
+ String patternDir = patternDirs[i];
+ if (!matchDirectory(inputDir, patternDir)) {
+ return false;
+ }
+ }
+ return true;
+ } else if (pattern.contains(";") && !input.contains(";")) {
+ return !input.contains(",");
+ } else if (!pattern.contains(";") && input.contains(";")) {
+ return false;
+ }
+ return matchDirectory(input, pattern);
+ }
+
+ private static boolean matchDirectory(String inputDir, String patternDir) {
+ String[] inputLevels = inputDir.split(",");
+ String[] patternLevels = patternDir.split(",");
+ return inputLevels.length == patternLevels.length || inputLevels.length ==
1;
+ }
+
+ private static void initDataNodeProperties(Properties properties) {
+ if (properties.getProperty("dn_system_dir") == null) {
+ properties.setProperty("dn_system_dir", DEFAULT_DN_SYSTEM_DIR);
+ }
+ if (properties.getProperty("dn_consensus_dir") == null) {
+ properties.setProperty("dn_consensus_dir", DEFAULT_DN_CONSENSUS_DIR);
+ }
+ if (properties.getProperty("dn_data_dirs") == null) {
+ properties.setProperty("dn_data_dirs", DEFAULT_DN_DATA_DIRS);
+ }
+ if (properties.getProperty("dn_tracing_dir") == null) {
+ properties.setProperty("dn_tracing_dir", DEFAULT_DN_TRACING_DIR);
+ }
+ if (properties.getProperty("dn_wal_dirs") == null) {
+ properties.setProperty("dn_wal_dirs", DEFAULT_DN_WAL_DIRS);
+ }
+ }
+
+ private static void initConfigNodeProperties(Properties properties) {
+
+ if (properties.getProperty("cn_system_dir") == null) {
+ properties.setProperty("cn_system_dir", DEFAULT_CN_SYSTEM_DIR);
+ }
+ if (properties.getProperty("cn_consensus_dir") == null) {
+ properties.setProperty("cn_consensus_dir", DEFAULT_CN_CONSENSUS_DIR);
+ }
+ }
+
+ private static Properties getProperties(String configName) {
+ URL url = ioTDBDescriptor.getPropsUrl(configName);
+ Properties properties = new Properties();
+ if (url != null) {
+ try (InputStream inputStream = url.openStream()) {
+ LOGGER.info("Start to read config file {}", url);
+ properties.load(new InputStreamReader(inputStream,
StandardCharsets.UTF_8));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ return properties;
+ }
+
+ private static boolean filesAreEqual(Path file1, Path file2) throws
IOException {
+ long size1 = Files.size(file1);
+ long size2 = Files.size(file2);
+ return size1 == size2;
+ }
+
+ public static void compareAndcopyDirectory(File sourceDirectory, File
targetDirectory) {
+ try {
+ Files.walkFileTree(
+ sourceDirectory.toPath(),
+ new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes
attrs)
+ throws IOException {
+ Path targetFile =
+
targetDirectory.toPath().resolve(sourceDirectory.toPath().relativize(file));
+ if (Files.exists(file)) {
+ cpmm.put(file.toFile().getAbsolutePath(), "1");
+ targetFileCount.incrementAndGet();
+ if (!Files.exists(targetFile) || !filesAreEqual(file,
targetFile)) {
+ Files.copy(file, targetFile,
StandardCopyOption.REPLACE_EXISTING);
+ }
+ }
+ if (processFileCount.get() > targetFileCount.get()) {
+ writeFileData(filename, processFileCount.get());
+ LOGGER.info(
+ "total file number:" + fileCount + ",backup file number:"
+ processFileCount);
+ } else {
+ writeFileData(filename, targetFileCount.get());
+ LOGGER.info(
+ "total file number:" + fileCount + ",backup file number:"
+ targetFileCount);
+ }
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attrs)
+ throws IOException {
+ Path targetDir =
+
targetDirectory.toPath().resolve(sourceDirectory.toPath().relativize(dir));
+ if (!Files.exists(targetDir)) {
+ Files.createDirectories(targetDir);
+ }
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ } catch (IOException e) {
+ LOGGER.error("copy file error {}", sourceDirectory, e);
+ }
+ }
+
+ public static void createDirectory(String directoryPath) {
+ File directory = new File(directoryPath);
+ if (!directory.exists()) {
+ boolean created = directory.mkdirs();
+ if (created) {
+ LOGGER.info("Directory created successfully:{}", directoryPath);
+ } else {
+ LOGGER.error("Failed to create directory:{}", directoryPath);
+ }
+ }
+ }
+
+ public static void compareAndLinkDirectory(File sourceDirectory, File
targetDirectory) {
+ try {
+ Files.walkFileTree(
+ sourceDirectory.toPath(),
+ new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes
attrs)
+ throws IOException {
+ Path targetFile =
+
targetDirectory.toPath().resolve(sourceDirectory.toPath().relativize(file));
+ if (Files.exists(file)) {
+ cpmm.put(file.toFile().getAbsolutePath(), "1");
+ targetFileCount.incrementAndGet();
+ if (!Files.exists(targetFile) || !filesAreEqual(file,
targetFile)) {
+ try {
+ Files.createLink(targetFile, file);
+ } catch (UnsupportedOperationException | IOException e) {
+ LOGGER.error("link file error {}", sourceDirectory, e);
+ try {
+ Files.copy(file, targetFile,
StandardCopyOption.REPLACE_EXISTING);
+ } catch (IOException ex) {
+ targetFileCount.decrementAndGet();
+ LOGGER.error("copy file error {}", sourceDirectory, ex);
+ }
+ }
+ }
+ }
+ if (processFileCount.get() > targetFileCount.get()) {
+ writeFileData(filename, processFileCount.get());
+ LOGGER.info(
+ "total file number:" + fileCount + ",backup file number:"
+ processFileCount);
+
+ } else {
+ writeFileData(filename, targetFileCount.get());
+ LOGGER.info(
+ "total file number:" + fileCount + ",backup file number:"
+ targetFileCount);
+ }
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attrs)
+ throws IOException {
+ Path targetDir =
+
targetDirectory.toPath().resolve(sourceDirectory.toPath().relativize(dir));
+ if (!Files.exists(targetDir)) {
+ Files.createDirectories(targetDir);
+ }
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static String formatPathForOS(String path) {
+ String os = System.getProperty("os.name").toLowerCase();
+ if (os.contains("win")) {
+ return path.replace("\\", "\\\\");
+ } else {
+ return path;
+ }
+ }
+
+ public static void propertiesFileUpdate(String filePath, String key, String
newValue) {
+ try {
+ newValue = formatPathForOS(newValue);
+ FileInputStream fileInputStream = new FileInputStream(filePath);
+ BufferedReader reader = new BufferedReader(new
InputStreamReader(fileInputStream));
+
+ List<String> lines = new ArrayList<>();
+ String line;
+ while ((line = reader.readLine()) != null) {
+ lines.add(line);
+ }
+ reader.close();
+ boolean keyFound = false;
+
+ for (int i = 0; i < lines.size(); i++) {
+ String currentLine = lines.get(i);
+ currentLine = currentLine.trim();
+ if (currentLine.startsWith("#") &&
currentLine.substring(1).trim().equals(key)) {
+ } else if (currentLine.contains("=")) {
+ int equalsIndex = currentLine.indexOf("=");
+ String propertyKey = currentLine.substring(0, equalsIndex).trim();
+ if (propertyKey.equals(key)) {
+ lines.set(i, propertyKey + "=" + newValue);
+ keyFound = true;
+ break;
+ }
+ }
+ }
+ if (!keyFound) {
+ lines.add(key + "=" + newValue);
+ }
+
+ FileOutputStream fileOutputStream = new FileOutputStream(filePath);
+ PrintWriter printWriter = new PrintWriter(fileOutputStream);
+ for (String fileLine : lines) {
+ printWriter.println(fileLine);
+ }
+
+ printWriter.close();
+ fileOutputStream.close();
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static int countFiles(String directoryPath) {
+ countFilesRecursively(new File(directoryPath), fileCount);
+ return fileCount.get();
+ }
+
+ private static void countFilesRecursively(File file, AtomicInteger
fileCount) {
+
+ if (file.isDirectory() && file.exists()) {
+ File[] files = file.listFiles();
+ if (files != null) {
+ for (File subFile : files) {
+ countFilesRecursively(subFile, fileCount);
+ }
+ }
+ } else {
+ if (file.exists()) {
+ mm.put(file.getAbsolutePath(), "1");
+ fileCount.incrementAndGet();
+ }
+ }
+ }
+
+ public static int readFileData(String filename) {
+ Path filePath = Paths.get(filename);
+ createFile(filename);
+
+ try {
+ List<String> lines = Files.readAllLines(filePath,
StandardCharsets.UTF_8);
+ if (!lines.isEmpty()) {
+ return Integer.parseInt(lines.get(0));
+ }
+ } catch (IOException e) {
+ LOGGER.error("Failed to read data from file: {}", filename, e);
+ }
+ return 0;
+ }
+
+ public static void delFile(String filename) {
+ File file = new File(filename);
+ if (file.exists()) {
+ file.delete();
+ }
+ }
+
+ public static void writeFileData(String filename, int data) {
+ Path filePath = Paths.get(filename);
+ try {
+ Files.write(filePath,
Integer.toString(data).getBytes(StandardCharsets.UTF_8));
+ } catch (IOException e) {
+ LOGGER.error("Failed to write data to file: {}", filename, e);
+ }
+ }
+
+ public static void createFile(String filename) {
+ Path filePath = Paths.get(filename);
+ if (!Files.exists(filePath)) {
+ try {
+ Files.createFile(filePath);
+ } catch (IOException e) {
+ LOGGER.error("Failed to create file: {}", filename, e);
+ }
+ }
+ }
+}