This is an automated email from the ASF dual-hosted git repository. JackieTien97 pushed a commit to branch edge-version in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 1e5de50df562385d0a72a5ed4e3eea6352677242 Author: JackieTien97 <[email protected]> AuthorDate: Fri Aug 28 15:59:01 2026 +0800 Add IoTDB Edge distribution: ConfigNode + DataNode merged in one JVM Produce apache-iotdb-edge-${version}-all-bin from the default distribution build, targeting resource-constrained edge machines that share the host with other processes (about 512 MB total process RSS by default). - EdgeNode (iotdb-core/confignode, org.apache.iotdb.edge): bootstraps the ConfigNode on a background thread, waits for its internal RPC port, then starts the DataNode in the same JVM, saving a whole JVM's fixed overhead (~140 MB validated on x86 and Raspberry Pi 4B). - One pair of lifecycle scripts only: sbin/start-edge.sh / stop-edge.sh (plus Windows bats); no separate ConfigNode/DataNode scripts in this package. start-edge.sh sets CONFIGNODE_HOME explicitly so the ConfigNode resolves its directories against the installation dir. - conf/edge-env.sh: fixed small JVM budget (Xmx 224M, direct 96M, metaspace 160m, SerialGC, Xss320k, ActiveProcessorCount=2). - Edge-tuned iotdb-system.properties defaults: small thread pools, 1M WAL buffer, 4M tsfile write buffer, 128M compaction target, CUSTOM region policy with 1 region group per database, series_slot_num=1, metrics off. - Validated at 1 Hz mixed read/write on x86 (>=20k series) and Raspberry Pi 4B (>=10k series, 30-min soak per shape, zero failed points). --- distribution/pom.xml | 16 ++ distribution/src/assembly/all.xml | 4 + distribution/src/assembly/{all.xml => edge.xml} | 40 ++-- .../resources/conf-edge/iotdb-system.properties | 126 +++++++++++ .../assembly/resources/conf-edge/logback-edge.xml | 252 +++++++++++++++++++++ .../iotdb/confignode/i18n/ConfigNodeMessages.java | 9 + .../iotdb/confignode/i18n/ConfigNodeMessages.java | 9 + .../main/java/org/apache/iotdb/edge/EdgeNode.java | 114 ++++++++++ scripts/conf/edge-env.sh | 69 ++++++ scripts/conf/windows/edge-env.bat | 44 ++++ scripts/sbin/start-edge.sh | 92 ++++++++ scripts/sbin/stop-edge.sh | 45 ++++ scripts/sbin/windows/start-edge.bat | 105 +++++++++ scripts/sbin/windows/stop-edge.bat | 23 ++ 14 files changed, 935 insertions(+), 13 deletions(-) diff --git a/distribution/pom.xml b/distribution/pom.xml index 3e618451f58..f14b9deeda4 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -93,6 +93,21 @@ <finalName>apache-iotdb-${project.version}</finalName> </configuration> </execution> + <!-- Edge distribution: ConfigNode + DataNode merged in one JVM, + with resource-constrained default configuration. --> + <execution> + <id>edge-bin</id> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <descriptors> + <descriptor>src/assembly/edge.xml</descriptor> + </descriptors> + <finalName>apache-iotdb-edge-${project.version}</finalName> + </configuration> + </execution> </executions> </plugin> <!-- @@ -123,6 +138,7 @@ <include>apache-iotdb-${project.version}-confignode-bin.zip</include> <include>apache-iotdb-${project.version}-library-udf-bin.zip</include> <include>apache-iotdb-${project.version}-external-service-impl-bin.zip</include> + <include>apache-iotdb-edge-${project.version}-all-bin.zip</include> </includes> </fileSet> </fileSets> diff --git a/distribution/src/assembly/all.xml b/distribution/src/assembly/all.xml index c8b583de664..10b6f09589a 100644 --- a/distribution/src/assembly/all.xml +++ b/distribution/src/assembly/all.xml @@ -64,6 +64,8 @@ <excludes> <exclude>ainode-env.*</exclude> <exclude>**/ainode-env.*</exclude> + <exclude>edge-env.*</exclude> + <exclude>**/edge-env.*</exclude> <exclude>iotdb-common.sh</exclude> <exclude>**/iotdb-common.bat</exclude> </excludes> @@ -85,6 +87,8 @@ <excludes> <exclude>*ainode.*</exclude> <exclude>**/*ainode.*</exclude> + <exclude>*edge.*</exclude> + <exclude>**/*edge.*</exclude> </excludes> <fileMode>0755</fileMode> </fileSet> diff --git a/distribution/src/assembly/all.xml b/distribution/src/assembly/edge.xml similarity index 77% copy from distribution/src/assembly/all.xml copy to distribution/src/assembly/edge.xml index c8b583de664..16055237409 100644 --- a/distribution/src/assembly/all.xml +++ b/distribution/src/assembly/edge.xml @@ -25,7 +25,7 @@ <format>dir</format> <format>zip</format> </formats> - <baseDirectory>apache-iotdb-${project.version}-all-bin</baseDirectory> + <baseDirectory>apache-iotdb-edge-${project.version}-all-bin</baseDirectory> <dependencySets> <dependencySet> <includes> @@ -46,27 +46,35 @@ </dependencySet> </dependencySets> <fileSets> + <!-- jmx credentials and the tool logback come from the datanode resources; + logback-datanode.xml is replaced by the merged logback-edge.xml below. --> <fileSet> <outputDirectory>conf</outputDirectory> <directory>${project.basedir}/../iotdb-core/datanode/src/assembly/resources/conf</directory> + <excludes> + <exclude>logback-datanode.xml</exclude> + </excludes> </fileSet> + <!-- iotdb-system.properties is replaced by the edge-tuned one below. --> <fileSet> <outputDirectory>conf</outputDirectory> - <directory>${project.basedir}/../iotdb-core/confignode/src/assembly/resources/conf</directory> + <directory>${project.basedir}/../iotdb-core/node-commons/src/assembly/resources/conf</directory> + <excludes> + <exclude>iotdb-system.properties</exclude> + </excludes> </fileSet> + <!-- edge-specific configuration: tuned iotdb-system.properties + merged logback. --> <fileSet> <outputDirectory>conf</outputDirectory> - <directory>${project.basedir}/../iotdb-core/node-commons/src/assembly/resources/conf</directory> + <directory>${project.basedir}/src/assembly/resources/conf-edge</directory> </fileSet> <fileSet> <outputDirectory>conf</outputDirectory> <directory>${project.basedir}/../scripts/conf</directory> - <excludes> - <exclude>ainode-env.*</exclude> - <exclude>**/ainode-env.*</exclude> - <exclude>iotdb-common.sh</exclude> - <exclude>**/iotdb-common.bat</exclude> - </excludes> + <includes> + <include>edge-env.sh</include> + <include>windows/edge-env.bat</include> + </includes> <fileMode>0755</fileMode> </fileSet> <fileSet> @@ -79,13 +87,19 @@ <filtered>true</filtered> <fileMode>0755</fileMode> </fileSet> + <!-- one pair of start/stop scripts for the merged process, plus the cli. --> <fileSet> <outputDirectory>sbin</outputDirectory> <directory>${project.basedir}/../scripts/sbin</directory> - <excludes> - <exclude>*ainode.*</exclude> - <exclude>**/*ainode.*</exclude> - </excludes> + <includes> + <include>start-edge.sh</include> + <include>stop-edge.sh</include> + <include>start-cli.sh</include> + <include>windows/start-edge.bat</include> + <include>windows/stop-edge.bat</include> + <include>windows/start-cli.bat</include> + <include>windows/start-cli-table.bat</include> + </includes> <fileMode>0755</fileMode> </fileSet> <fileSet> diff --git a/distribution/src/assembly/resources/conf-edge/iotdb-system.properties b/distribution/src/assembly/resources/conf-edge/iotdb-system.properties new file mode 100644 index 00000000000..e76a17a231c --- /dev/null +++ b/distribution/src/assembly/resources/conf-edge/iotdb-system.properties @@ -0,0 +1,126 @@ +# +# 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. +# + +#################### +### Cluster Configuration +#################### + +cluster_name=defaultCluster + +#################### +### Seed ConfigNode +#################### + +cn_seed_config_node=127.0.0.1:10710 + +dn_seed_config_node=127.0.0.1:10710 + +#################### +### Node RPC Configuration +#################### + +cn_internal_address=127.0.0.1 +cn_internal_port=10710 +cn_consensus_port=10720 + +dn_rpc_address=127.0.0.1 +dn_rpc_port=6667 +dn_internal_address=127.0.0.1 +dn_internal_port=10730 +dn_mpp_data_exchange_port=10740 +dn_schema_region_consensus_port=10750 +dn_data_region_consensus_port=10760 + +#################### +### Replication configuration +#################### + +schema_replication_factor=1 +data_replication_factor=1 + +#################### +### Directory Configuration +#################### + +# dn_data_dirs=data/datanode/data +# dn_wal_dirs=data/datanode/wal + +#################### +### Metric Configuration +#################### + +# cn_metric_reporter_list= +cn_metric_prometheus_reporter_port=9091 + +# dn_metric_reporter_list= +dn_metric_prometheus_reporter_port=9092 + +#################### +### IoTDB Edge Tuning +#################### +# The following defaults are tuned for the edge distribution: ConfigNode and +# DataNode run in ONE JVM with a small fixed memory budget (see conf/edge-env.sh), +# sharing the machine with other processes. Validated on x86 and Raspberry Pi 4B. + +# ---- thread pools (small fixed sizes instead of CPU-core-based defaults) ---- +query_thread_count=2 +degree_of_query_parallelism=1 +mpp_data_exchange_core_pool_size=2 +mpp_data_exchange_max_pool_size=2 +flush_thread_count=2 +compaction_thread_count=2 +sub_compaction_thread_count=1 +compaction_schedule_thread_num=1 +pipe_subtask_executor_max_thread_num=2 +pipe_sink_selector_number=1 +pipe_sink_max_client_number=8 +model_inference_execution_thread_count=1 +continuous_query_submit_thread_count=1 +into_operation_execution_thread_count=1 +procedure_core_worker_thread_count=2 +partition_table_recover_worker_num=2 +max_sub_task_num_for_information_table_scan=1 +load_active_listening_max_thread_num=1 +dn_selector_thread_nums_of_client_manager=1 +cn_selector_thread_nums_of_client_manager=1 +max_allowed_concurrent_queries=100 + +# ---- memory / file buffers ---- +wal_buffer_size_in_byte=1048576 +group_size_in_byte=4194304 +target_compaction_file_size=134217728 +into_operation_buffer_size_in_byte=8388608 +batch_size=10000 +schema_region_ratis_log_appender_buffer_size_max=4194304 +config_node_ratis_log_appender_buffer_size_max=4194304 + +# ---- background io politeness (share disks with other processes) ---- +compaction_write_throughput_mb_per_sec=8 +partition_table_recover_max_read_mb_per_sec=5 + +# ---- single-node region / partition layout ---- +schema_region_group_extension_policy=CUSTOM +default_schema_region_group_num_per_database=1 +data_region_group_extension_policy=CUSTOM +default_data_region_group_num_per_database=1 +series_slot_num=1 + +# ---- metrics off (the internal MetricService is shared by both nodes) ---- +cn_metric_level=OFF +dn_metric_level=OFF diff --git a/distribution/src/assembly/resources/conf-edge/logback-edge.xml b/distribution/src/assembly/resources/conf-edge/logback-edge.xml new file mode 100644 index 00000000000..58d31b8e84d --- /dev/null +++ b/distribution/src/assembly/resources/conf-edge/logback-edge.xml @@ -0,0 +1,252 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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. + +--> +<configuration scan="true" scanPeriod="60 seconds"> + <jmxConfigurator/> + <!-- prevent logback from outputting its own status at the start of every log --> + <statusListener class="ch.qos.logback.core.status.NopStatusListener"/> + <appender class="ch.qos.logback.core.rolling.RollingFileAppender" name="FILEERROR"> + <file>${IOTDB_HOME}/logs/log_edge_error.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${IOTDB_HOME}/logs/log-edge-error-%d{yyyyMMdd}.log.gz</fileNamePattern> + <maxHistory>30</maxHistory> + </rollingPolicy> + <append>true</append> + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> + <pattern>%d [%t] %-5p %C{25}:%L - %m %n</pattern> + <charset>utf-8</charset> + </encoder> + <filter class="ch.qos.logback.classic.filter.LevelFilter"> + <level>error</level> + <onMatch>ACCEPT</onMatch> + <onMismatch>DENY</onMismatch> + </filter> + </appender> + <appender class="ch.qos.logback.core.rolling.RollingFileAppender" name="FILEWARN"> + <file>${IOTDB_HOME}/logs/log_edge_warn.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${IOTDB_HOME}/logs/log-edge-warn-%d{yyyyMMdd}.log.gz</fileNamePattern> + <maxHistory>30</maxHistory> + </rollingPolicy> + <append>true</append> + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> + <pattern>%d [%t] %-5p %C{25}:%L - %m %n</pattern> + <charset>utf-8</charset> + </encoder> + <filter class="ch.qos.logback.classic.filter.LevelFilter"> + <level>WARN</level> + <onMatch>ACCEPT</onMatch> + <onMismatch>DENY</onMismatch> + </filter> + </appender> + <appender class="ch.qos.logback.core.rolling.RollingFileAppender" name="FILEDEBUG"> + <file>${IOTDB_HOME}/logs/log_edge_debug.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${IOTDB_HOME}/logs/log-edge-debug-%d{yyyyMMdd}.log.gz</fileNamePattern> + <maxHistory>30</maxHistory> + </rollingPolicy> + <append>true</append> + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> + <pattern>%d [%t] %-5p %C{25}:%L - %m %n</pattern> + <charset>utf-8</charset> + </encoder> + <filter class="ch.qos.logback.classic.filter.LevelFilter"> + <level>DEBUG</level> + <onMatch>ACCEPT</onMatch> + <onMismatch>DENY</onMismatch> + </filter> + </appender> + <appender class="ch.qos.logback.core.rolling.RollingFileAppender" name="FILETRACE"> + <file>${IOTDB_HOME}/logs/log_edge_trace.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${IOTDB_HOME}/logs/log-edge-trace-%d{yyyyMMdd}.log.gz</fileNamePattern> + <maxHistory>30</maxHistory> + </rollingPolicy> + <append>true</append> + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> + <pattern>%d [%t] %-5p %C{25}:%L - %m %n</pattern> + <charset>utf-8</charset> + </encoder> + <filter class="ch.qos.logback.classic.filter.LevelFilter"> + <level>TRACE</level> + <onMatch>ACCEPT</onMatch> + <onMismatch>DENY</onMismatch> + </filter> + </appender> + <appender class="ch.qos.logback.core.ConsoleAppender" name="stdout"> + <Target>System.out</Target> + <encoder> + <pattern>%d [%t] %-5p %C{25}:%L - %m %n</pattern> + <charset>utf-8</charset> + </encoder> + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + <level>${CONSOLE_LOG_LEVEL:-DEBUG}</level> + </filter> + </appender> + <!-- a log appender that collect all log records whose level is greater than debug--> + <appender class="ch.qos.logback.core.rolling.RollingFileAppender" name="FILEALL"> + <file>${IOTDB_HOME}/logs/log_edge_all.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${IOTDB_HOME}/logs/log-edge-all-%d{yyyyMMdd}.log.gz</fileNamePattern> + <maxHistory>30</maxHistory> + </rollingPolicy> + <append>true</append> + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> + <pattern>%d [%t] %-5p %C{25}:%L - %m %n</pattern> + <charset>utf-8</charset> + </encoder> + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + <level>INFO</level> + </filter> + </appender> + <appender class="ch.qos.logback.core.rolling.RollingFileAppender" name="FILE_COST_MEASURE"> + <file>${IOTDB_HOME}/logs/log_edge_measure.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${IOTDB_HOME}/logs/log-edge-measure-%d{yyyyMMdd}.log.gz</fileNamePattern> + <maxHistory>30</maxHistory> + </rollingPolicy> + <append>true</append> + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> + <pattern>%d [%t] %-5p %C{25}:%L - %m %n</pattern> + <charset>utf-8</charset> + </encoder> + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + <level>INFO</level> + </filter> + </appender> + <appender class="ch.qos.logback.core.rolling.RollingFileAppender" name="QUERY_DEBUG"> + <file>${IOTDB_HOME}/logs/log_edge_query_debug.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${IOTDB_HOME}/logs/log-edge-query-debug-%d{yyyyMMdd}.log.gz</fileNamePattern> + <maxHistory>30</maxHistory> + </rollingPolicy> + <append>true</append> + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> + <pattern>%d [%t] %C{25}:%L - %m %n</pattern> + <charset>utf-8</charset> + </encoder> + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + <level>INFO</level> + </filter> + </appender> + <appender class="ch.qos.logback.core.rolling.RollingFileAppender" name="SLOW_SQL"> + <file>${IOTDB_HOME}/logs/log_edge_slow_sql.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${IOTDB_HOME}/logs/log-edge-slow-sql-%d{yyyyMMdd}.log.gz</fileNamePattern> + <maxHistory>30</maxHistory> + </rollingPolicy> + <append>true</append> + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> + <pattern>%d [%t] %-5p %C{25}:%L - %m %n</pattern> + <charset>utf-8</charset> + </encoder> + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + <level>INFO</level> + </filter> + </appender> + <appender class="ch.qos.logback.core.rolling.RollingFileAppender" name="SAMPLED_QUERIES"> + <file>${IOTDB_HOME}/logs/log_edge_sampled_queries.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${IOTDB_HOME}/logs/log-edge-sampled-queries-%d{yyyyMMdd}.log.gz</fileNamePattern> + <maxHistory>30</maxHistory> + </rollingPolicy> + <append>true</append> + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> + <pattern>%d %m %n</pattern> + <charset>utf-8</charset> + </encoder> + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + <level>INFO</level> + </filter> + </appender> + <appender class="ch.qos.logback.core.rolling.RollingFileAppender" name="COMPACTION"> + <file>${IOTDB_HOME}/logs/log_edge_compaction.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${IOTDB_HOME}/logs/log-edge-compaction-%d{yyyyMMdd}.log.gz</fileNamePattern> + <maxHistory>30</maxHistory> + </rollingPolicy> + <append>true</append> + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> + <pattern>%d [%t] %-5p %C{25}:%L - %m %n</pattern> + <charset>utf-8</charset> + </encoder> + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + <level>INFO</level> + </filter> + </appender> + <appender class="ch.qos.logback.core.rolling.RollingFileAppender" name="EXPLAIN_ANALYZE"> + <file>${IOTDB_HOME}/logs/log_explain_analyze.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${IOTDB_HOME}/logs/log-edge-explain-%d{yyyyMMdd}.log.gz</fileNamePattern> + <maxHistory>30</maxHistory> + </rollingPolicy> + <append>true</append> + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> + <pattern>%d [%t] %-5p %C{25}:%L - %m %n</pattern> + <charset>utf-8</charset> + </encoder> + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + <level>INFO</level> + </filter> + </appender> + <root level="info"> + <appender-ref ref="FILETRACE"/> + <appender-ref ref="FILEDEBUG"/> + <appender-ref ref="FILEWARN"/> + <appender-ref ref="FILEERROR"/> + <appender-ref ref="FILEALL"/> + <appender-ref ref="stdout"/> + </root> + <logger level="OFF" name="io.moquette.broker.metrics.MQTTMessageLogger"/> + <logger level="info" name="org.apache.iotdb.db.service"/> + <logger level="info" name="org.apache.iotdb.db.conf"/> + <logger level="info" name="org.apache.iotdb.db.cost.statistic"> + <appender-ref ref="FILE_COST_MEASURE"/> + </logger> + <logger level="info" name="QUERY_DEBUG"> + <appender-ref ref="QUERY_DEBUG"/> + </logger> + <logger level="info" name="SLOW_SQL" additivity="false"> + <appender-ref ref="SLOW_SQL"/> + </logger> + <logger level="info" name="SAMPLED_QUERIES" additivity="false"> + <appender-ref ref="SAMPLED_QUERIES"/> + </logger> + <logger level="info" name="QUERY_FREQUENCY"> + <appender-ref ref="QUERY_FREQUENCY"/> + </logger> + <logger level="info" name="DETAILED_FAILURE_QUERY_TRACE"/> + <logger level="info" name="COMPACTION"> + <appender-ref ref="COMPACTION"/> + </logger> + <logger level="info" name="org.apache.iotdb.pipe.api"> + <appender-ref ref="PIPE"/> + </logger> + <logger level="info" name="org.apache.iotdb.db.pipe"> + <appender-ref ref="PIPE"/> + </logger> + <logger level="info" name="org.apache.iotdb.commons.pipe"> + <appender-ref ref="PIPE"/> + </logger> + <logger level="info" name="EXPLAIN_ANALYZE" additivity="false"> + <appender-ref ref="EXPLAIN_ANALYZE"/> + </logger> +</configuration> diff --git a/iotdb-core/confignode/src/main/i18n/en/org/apache/iotdb/confignode/i18n/ConfigNodeMessages.java b/iotdb-core/confignode/src/main/i18n/en/org/apache/iotdb/confignode/i18n/ConfigNodeMessages.java index c4832cd886c..800d59bf727 100644 --- a/iotdb-core/confignode/src/main/i18n/en/org/apache/iotdb/confignode/i18n/ConfigNodeMessages.java +++ b/iotdb-core/confignode/src/main/i18n/en/org/apache/iotdb/confignode/i18n/ConfigNodeMessages.java @@ -678,4 +678,13 @@ public final class ConfigNodeMessages { public static final String EXCEPTION_FAILED_TO_CREATE_OR_ALTER_TOPIC_SUBSCRIBING_ONLY_TO_THE_AUDIT_DATABASE_OR_PATHS_UNDER_IT_IS_NOT_ALLOWED_3E96A6BA = "Failed to create or alter topic, subscribing only to the __audit database or paths under it is not allowed"; + public static final String LOG_STARTING_IOTDB_EDGE_CONFIGNODE_AND_DATANODE_IN_ONE_77F32605 = + "Starting IoTDB Edge: ConfigNode and DataNode in one process"; + public static final String LOG_IOTDB_EDGE_CONFIGNODE_IS_READY_STARTING_DATANODE_6729159E = + "IoTDB Edge: ConfigNode is ready, starting DataNode"; + public static final String EXCEPTION_IOTDB_EDGE_CONFIGNODE_BOOTSTRAP_FAILED_02EEE59A = + "IoTDB Edge: ConfigNode bootstrap failed"; + public static final String + EXCEPTION_IOTDB_EDGE_CONFIGNODE_INTERNAL_PORT_ARG_IS_NOT_READY_WITHIN_03697FF5 = + "IoTDB Edge: ConfigNode internal port %s is not ready within %s ms"; } diff --git a/iotdb-core/confignode/src/main/i18n/zh/org/apache/iotdb/confignode/i18n/ConfigNodeMessages.java b/iotdb-core/confignode/src/main/i18n/zh/org/apache/iotdb/confignode/i18n/ConfigNodeMessages.java index 3029154ab3e..14713cbb801 100644 --- a/iotdb-core/confignode/src/main/i18n/zh/org/apache/iotdb/confignode/i18n/ConfigNodeMessages.java +++ b/iotdb-core/confignode/src/main/i18n/zh/org/apache/iotdb/confignode/i18n/ConfigNodeMessages.java @@ -721,4 +721,13 @@ public final class ConfigNodeMessages { public static final String EXCEPTION_FAILED_TO_CREATE_OR_ALTER_TOPIC_SUBSCRIBING_ONLY_TO_THE_AUDIT_DATABASE_OR_PATHS_UNDER_IT_IS_NOT_ALLOWED_3E96A6BA = "创建或修改 topic 失败,不允许仅订阅 __audit 数据库或其下的路径"; + public static final String LOG_STARTING_IOTDB_EDGE_CONFIGNODE_AND_DATANODE_IN_ONE_77F32605 = + "正在启动 IoTDB Edge:ConfigNode 与 DataNode 运行于同一进程"; + public static final String LOG_IOTDB_EDGE_CONFIGNODE_IS_READY_STARTING_DATANODE_6729159E = + "IoTDB Edge:ConfigNode 已就绪,开始启动 DataNode"; + public static final String EXCEPTION_IOTDB_EDGE_CONFIGNODE_BOOTSTRAP_FAILED_02EEE59A = + "IoTDB Edge:ConfigNode 启动失败"; + public static final String + EXCEPTION_IOTDB_EDGE_CONFIGNODE_INTERNAL_PORT_ARG_IS_NOT_READY_WITHIN_03697FF5 = + "IoTDB Edge:ConfigNode 内部端口 %s 在 %s ms 内未就绪"; } diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/edge/EdgeNode.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/edge/EdgeNode.java new file mode 100644 index 00000000000..061e12602d6 --- /dev/null +++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/edge/EdgeNode.java @@ -0,0 +1,114 @@ +/* + * 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.edge; + +import org.apache.iotdb.confignode.conf.ConfigNodeDescriptor; +import org.apache.iotdb.confignode.i18n.ConfigNodeMessages; +import org.apache.iotdb.confignode.service.ConfigNode; +import org.apache.iotdb.db.service.DataNode; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.InetSocketAddress; +import java.net.Socket; + +/** + * Entry point of the IoTDB Edge distribution: starts the ConfigNode and the DataNode services + * inside ONE JVM process, so that a resource-constrained edge machine only pays a single JVM's + * fixed overhead (metaspace, code cache, GC structures, thread stacks). + * + * <p>The ConfigNode is bootstrapped on a background thread first; once its internal RPC port + * accepts connections (i.e. the seed ConfigNode finished its consensus initialization), the + * DataNode is started on the main thread. Both services then keep the JVM alive with their own + * non-daemon threads. If either node fails fatally, its own error handling terminates the whole + * process, which is the intended single-process semantics of the edge deployment. + * + * <p>Note for launchers: both {@code CONFIGNODE_HOME} and {@code IOTDB_HOME} system properties must + * point to the installation directory (see {@code sbin/start-edge.sh}), otherwise the ConfigNode + * resolves its data directories against the process working directory. + */ +public final class EdgeNode { + + private static final Logger LOGGER = LoggerFactory.getLogger(EdgeNode.class); + + /** Max duration to wait for the ConfigNode internal RPC port to accept connections. */ + private static final long CONFIG_NODE_READY_TIMEOUT_MS = 300_000L; + + private static final long PORT_PROBE_INTERVAL_MS = 500L; + + /** Extra delay after the port opens, leaving time for the leader election to settle. */ + private static final long LEADER_ELECTION_GRACE_MS = 5_000L; + + private EdgeNode() {} + + public static void main(String[] args) throws Exception { + LOGGER.info(ConfigNodeMessages.LOG_STARTING_IOTDB_EDGE_CONFIGNODE_AND_DATANODE_IN_ONE_77F32605); + + final Throwable[] configNodeError = new Throwable[1]; + Thread configNodeThread = + new Thread( + () -> { + try { + ConfigNode.main(new String[] {"-s"}); + } catch (Throwable t) { + configNodeError[0] = t; + } + }, + "EdgeNode-ConfigNode-Bootstrap"); + configNodeThread.start(); + + int internalPort = ConfigNodeDescriptor.getInstance().getConf().getInternalPort(); + waitPortOpen(internalPort, configNodeError); + if (configNodeError[0] != null) { + throw new IllegalStateException( + ConfigNodeMessages.EXCEPTION_IOTDB_EDGE_CONFIGNODE_BOOTSTRAP_FAILED_02EEE59A, + configNodeError[0]); + } + Thread.sleep(LEADER_ELECTION_GRACE_MS); + LOGGER.info(ConfigNodeMessages.LOG_IOTDB_EDGE_CONFIGNODE_IS_READY_STARTING_DATANODE_6729159E); + + // DataNode.main returns after a successful start; the services of both nodes keep the JVM + // alive with non-daemon threads afterwards. + DataNode.main(new String[] {"-s"}); + } + + private static void waitPortOpen(int port, Throwable[] configNodeError) + throws InterruptedException { + long deadline = System.currentTimeMillis() + CONFIG_NODE_READY_TIMEOUT_MS; + while (System.currentTimeMillis() < deadline) { + if (configNodeError[0] != null) { + return; + } + try (Socket socket = new Socket()) { + socket.connect(new InetSocketAddress("127.0.0.1", port), 1000); + return; + } catch (Exception e) { + Thread.sleep(PORT_PROBE_INTERVAL_MS); + } + } + throw new IllegalStateException( + String.format( + ConfigNodeMessages + .EXCEPTION_IOTDB_EDGE_CONFIGNODE_INTERNAL_PORT_ARG_IS_NOT_READY_WITHIN_03697FF5, + port, + CONFIG_NODE_READY_TIMEOUT_MS)); + } +} diff --git a/scripts/conf/edge-env.sh b/scripts/conf/edge-env.sh new file mode 100644 index 00000000000..627623047d4 --- /dev/null +++ b/scripts/conf/edge-env.sh @@ -0,0 +1,69 @@ +#!/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. +# + +# IoTDB Edge runs ConfigNode and DataNode inside ONE JVM with a fixed, small +# memory budget so that it can share a machine with other processes. +# The defaults below target a total process RSS of about 512 MB and were +# validated on x86 servers and Raspberry Pi 4B class devices. + +# On-heap memory of the merged process. Example values: '224M', '512M'. +ON_HEAP_MEMORY="${ON_HEAP_MEMORY:-224M}" +# Initial heap. Kept small so an idle edge instance stays light. +INIT_HEAP_MEMORY="${INIT_HEAP_MEMORY:-64M}" +# Off-heap (direct buffer) memory. +OFF_HEAP_MEMORY="${OFF_HEAP_MEMORY:-96M}" + +if [ "${OFF_HEAP_MEMORY%"G"}" != "$OFF_HEAP_MEMORY" ]; then + off_heap_memory_size_in_mb=$(expr ${OFF_HEAP_MEMORY%"G"} \* 1024) +else + off_heap_memory_size_in_mb=$(expr ${OFF_HEAP_MEMORY%"M"}) +fi +# Max cached buffer size, which equals OFF_HEAP_MEMORY / io threads number (200) +MAX_CACHED_BUFFER_SIZE=$(expr $off_heap_memory_size_in_mb \* 1024 \* 1024 / 200) + +IOTDB_JMX_OPTS="$IOTDB_JMX_OPTS -Diotdb.jmx.local=true" +IOTDB_JMX_OPTS="$IOTDB_JMX_OPTS -Xms${INIT_HEAP_MEMORY}" +IOTDB_JMX_OPTS="$IOTDB_JMX_OPTS -Xmx${ON_HEAP_MEMORY}" +IOTDB_JMX_OPTS="$IOTDB_JMX_OPTS -XX:MaxDirectMemorySize=${OFF_HEAP_MEMORY}" +IOTDB_JMX_OPTS="$IOTDB_JMX_OPTS -Djdk.nio.maxCachedBufferSize=${MAX_CACHED_BUFFER_SIZE}" +IOTDB_JMX_OPTS="$IOTDB_JMX_OPTS -XX:+CrashOnOutOfMemoryError" +# Serial GC has the lowest fixed memory overhead; typical edge write rates leave +# plenty of latency headroom for its pauses. +IOTDB_JMX_OPTS="$IOTDB_JMX_OPTS -XX:+UseSerialGC" +IOTDB_JMX_OPTS="$IOTDB_JMX_OPTS -Xss320k" +IOTDB_JMX_OPTS="$IOTDB_JMX_OPTS -XX:MaxMetaspaceSize=160m" +IOTDB_JMX_OPTS="$IOTDB_JMX_OPTS -XX:CompressedClassSpaceSize=40m" +IOTDB_JMX_OPTS="$IOTDB_JMX_OPTS -XX:ReservedCodeCacheSize=64m" +# Cap the processors the JVM sees, shrinking internal thread pools on big hosts. +IOTDB_JMX_OPTS="$IOTDB_JMX_OPTS -XX:ActiveProcessorCount=2" +IOTDB_JMX_OPTS="$IOTDB_JMX_OPTS -XX:+UnlockDiagnosticVMOptions" +IOTDB_JMX_OPTS="$IOTDB_JMX_OPTS -XX:+UseCRC32Intrinsics" +IOTDB_JMX_OPTS="$IOTDB_JMX_OPTS -XX:SafepointTimeoutDelay=1000" +IOTDB_JMX_OPTS="$IOTDB_JMX_OPTS -XX:+SafepointTimeout" +IOTDB_JMX_OPTS="$IOTDB_JMX_OPTS -Dsun.jnu.encoding=UTF-8 -Dfile.encoding=UTF-8" + +# Append tsfile locale option populated by Maven at package time +# (see conf/iotdb-common.sh; empty in default build, "-Dtsfile.locale=zh" under with-zh-locale). +if [ -n "$TSFILE_LOCALE_JVM_OPT" ]; then + IOTDB_JMX_OPTS="$IOTDB_JMX_OPTS $TSFILE_LOCALE_JVM_OPT" +fi + +echo "IoTDB Edge on heap memory size = ${ON_HEAP_MEMORY}B, off heap memory size = ${OFF_HEAP_MEMORY}B" +echo "If you want to change this configuration, please check conf/edge-env.sh." diff --git a/scripts/conf/windows/edge-env.bat b/scripts/conf/windows/edge-env.bat new file mode 100644 index 00000000000..0554d765e97 --- /dev/null +++ b/scripts/conf/windows/edge-env.bat @@ -0,0 +1,44 @@ +@echo off +@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 + +@REM IoTDB Edge runs ConfigNode and DataNode inside ONE JVM with a fixed, small +@REM memory budget (about 512 MB total process RSS by default). + +if "%ON_HEAP_MEMORY%"=="" set ON_HEAP_MEMORY=224M +if "%INIT_HEAP_MEMORY%"=="" set INIT_HEAP_MEMORY=64M +if "%OFF_HEAP_MEMORY%"=="" set OFF_HEAP_MEMORY=96M + +set IOTDB_JMX_OPTS=%IOTDB_JMX_OPTS% -Diotdb.jmx.local=true +set IOTDB_JMX_OPTS=%IOTDB_JMX_OPTS% -Xms%INIT_HEAP_MEMORY% +set IOTDB_JMX_OPTS=%IOTDB_JMX_OPTS% -Xmx%ON_HEAP_MEMORY% +set IOTDB_JMX_OPTS=%IOTDB_JMX_OPTS% -XX:MaxDirectMemorySize=%OFF_HEAP_MEMORY% +set IOTDB_JMX_OPTS=%IOTDB_JMX_OPTS% -XX:+CrashOnOutOfMemoryError +set IOTDB_JMX_OPTS=%IOTDB_JMX_OPTS% -XX:+UseSerialGC +set IOTDB_JMX_OPTS=%IOTDB_JMX_OPTS% -Xss320k +set IOTDB_JMX_OPTS=%IOTDB_JMX_OPTS% -XX:MaxMetaspaceSize=160m +set IOTDB_JMX_OPTS=%IOTDB_JMX_OPTS% -XX:CompressedClassSpaceSize=40m +set IOTDB_JMX_OPTS=%IOTDB_JMX_OPTS% -XX:ReservedCodeCacheSize=64m +set IOTDB_JMX_OPTS=%IOTDB_JMX_OPTS% -XX:ActiveProcessorCount=2 +set IOTDB_JMX_OPTS=%IOTDB_JMX_OPTS% -XX:+UnlockDiagnosticVMOptions +set IOTDB_JMX_OPTS=%IOTDB_JMX_OPTS% -XX:+UseCRC32Intrinsics +set IOTDB_JMX_OPTS=%IOTDB_JMX_OPTS% -Dsun.jnu.encoding=UTF-8 -Dfile.encoding=UTF-8 + +echo IoTDB Edge on heap memory size = %ON_HEAP_MEMORY%B, off heap memory size = %OFF_HEAP_MEMORY%B +echo If you want to change this configuration, please check conf\windows\edge-env.bat. diff --git a/scripts/sbin/start-edge.sh b/scripts/sbin/start-edge.sh new file mode 100644 index 00000000000..6b5b9477b6b --- /dev/null +++ b/scripts/sbin/start-edge.sh @@ -0,0 +1,92 @@ +#!/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. +# + +# Start IoTDB Edge: ConfigNode + DataNode in one JVM process. + +if [ -z "${IOTDB_HOME}" ]; then + export IOTDB_HOME="$(cd "$(dirname "$0")"/.. && pwd)" +fi +if [ -z "${IOTDB_CONF}" ]; then + export IOTDB_CONF=${IOTDB_HOME}/conf +fi +export IOTDB_DATA_HOME=${IOTDB_DATA_HOME:-${IOTDB_HOME}} +export IOTDB_LOG_DIR=${IOTDB_LOG_DIR:-${IOTDB_HOME}/logs} +mkdir -p "${IOTDB_LOG_DIR}" + +# Refuse to start when any node port is already occupied. +for p in 10710 10720 6667 10730 10740 10750 10760; do + (echo > /dev/tcp/127.0.0.1/$p) 2>/dev/null && { echo "ERROR: port $p is already in use, IoTDB Edge cannot start."; exit 1; } +done + +if [ -f "${IOTDB_CONF}/iotdb-common.sh" ]; then + . "${IOTDB_CONF}/iotdb-common.sh" +fi +. "${IOTDB_CONF}/edge-env.sh" + +# find java in JAVA_HOME +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 + +illegal_access_params="" +illegal_access_params="$illegal_access_params --add-opens=java.base/java.util.concurrent=ALL-UNNAMED" +illegal_access_params="$illegal_access_params --add-opens=java.base/java.lang=ALL-UNNAMED" +illegal_access_params="$illegal_access_params --add-opens=java.base/java.util=ALL-UNNAMED" +illegal_access_params="$illegal_access_params --add-opens=java.base/java.nio=ALL-UNNAMED" +illegal_access_params="$illegal_access_params --add-opens=java.base/java.io=ALL-UNNAMED" +illegal_access_params="$illegal_access_params --add-opens=java.base/java.net=ALL-UNNAMED" + +CLASSPATH="" +for f in "${IOTDB_HOME}"/lib/*.jar; do + CLASSPATH=${CLASSPATH}":"$f +done + +iotdb_parms="-Dlogback.configurationFile=${IOTDB_CONF}/logback-edge.xml" +iotdb_parms="$iotdb_parms -DIOTDB_HOME=${IOTDB_HOME}" +# CONFIGNODE_HOME must also point to the installation directory, otherwise the +# ConfigNode part resolves its data directories against the working directory. +iotdb_parms="$iotdb_parms -DCONFIGNODE_HOME=${IOTDB_HOME}" +iotdb_parms="$iotdb_parms -DIOTDB_DATA_HOME=${IOTDB_DATA_HOME}" +iotdb_parms="$iotdb_parms -DTSFILE_HOME=${IOTDB_HOME}" +iotdb_parms="$iotdb_parms -DIOTDB_CONF=${IOTDB_CONF}" +iotdb_parms="$iotdb_parms -DCONFIGNODE_CONF=${IOTDB_CONF}" +iotdb_parms="$iotdb_parms -DTSFILE_CONF=${IOTDB_CONF}" +iotdb_parms="$iotdb_parms -Dname=iotdb.EdgeNode" +iotdb_parms="$iotdb_parms -DIOTDB_LOG_DIR=${IOTDB_LOG_DIR}" +iotdb_parms="$iotdb_parms -DCONFIGNODE_LOG_DIR=${IOTDB_LOG_DIR}" +iotdb_parms="$iotdb_parms -DOFF_HEAP_MEMORY=${OFF_HEAP_MEMORY}" + +classname=org.apache.iotdb.edge.EdgeNode + +echo "Starting IoTDB Edge (ConfigNode + DataNode in one process)" +nohup "$JAVA" $illegal_access_params $iotdb_parms $IOTDB_JMX_OPTS -cp "$CLASSPATH" "$classname" -s > "${IOTDB_LOG_DIR}/log_edge_console.log" 2>&1 & +echo $! > "${IOTDB_HOME}/edge.pid" +echo "IoTDB Edge started, pid $(cat "${IOTDB_HOME}/edge.pid"), console log: ${IOTDB_LOG_DIR}/log_edge_console.log" diff --git a/scripts/sbin/stop-edge.sh b/scripts/sbin/stop-edge.sh new file mode 100644 index 00000000000..b3944ca9db2 --- /dev/null +++ b/scripts/sbin/stop-edge.sh @@ -0,0 +1,45 @@ +#!/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. +# + +# Stop IoTDB Edge (the merged ConfigNode + DataNode process). + +IOTDB_HOME="$(cd "$(dirname "$0")"/.. && pwd)" + +if [ -f "${IOTDB_HOME}/edge.pid" ]; then + PID=$(cat "${IOTDB_HOME}/edge.pid") + if kill -0 "$PID" 2>/dev/null; then + kill "$PID" + for i in $(seq 1 30); do + kill -0 "$PID" 2>/dev/null || break + sleep 1 + done + if kill -0 "$PID" 2>/dev/null; then + kill -9 "$PID" + fi + echo "IoTDB Edge process $PID stopped." + else + echo "IoTDB Edge process $PID is not running." + fi + rm -f "${IOTDB_HOME}/edge.pid" +else + echo "No pid file found, trying to stop by process name." + pkill -f "org.apache.iotdb.edge.EdgeNode" 2>/dev/null +fi +exit 0 diff --git a/scripts/sbin/windows/start-edge.bat b/scripts/sbin/windows/start-edge.bat new file mode 100644 index 00000000000..42d452ce24c --- /dev/null +++ b/scripts/sbin/windows/start-edge.bat @@ -0,0 +1,105 @@ +@echo off +@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 + +@REM set cmd format +powershell -NoProfile -Command "$v=(Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion').CurrentMajorVersionNumber; if($v -gt 6) { cmd /c 'chcp 65001' }" + +title IoTDB Edge + +echo ```````````````````````` +echo Starting IoTDB Edge (ConfigNode + DataNode in one process) +echo ```````````````````````` + +@REM ----------------------------------------------------------------------------- +@REM SET JAVA +set PATH="%JAVA_HOME%\bin\";%PATH% +set "FULL_VERSION=" +set "MAJOR_VERSION=" +set "MINOR_VERSION=" + +for /f tokens^=2-5^ delims^=.-_+^" %%j in ('java -fullversion 2^>^&1') do ( + set "FULL_VERSION=%%j-%%k-%%l-%%m" + IF "%%j" == "1" ( + set "MAJOR_VERSION=%%k" + set "MINOR_VERSION=%%l" + ) else ( + set "MAJOR_VERSION=%%j" + set "MINOR_VERSION=%%k" + ) +) + +set JAVA_VERSION=%MAJOR_VERSION% + +@REM IoTDB requires JDK 17 or later. +IF "%JAVA_VERSION%" == "" ( + echo Failed to determine Java version. IoTDB only supports jdk ^>= 17, please check your java installation. + goto finally +) +IF %JAVA_VERSION% LSS 17 ( + echo IoTDB only supports jdk ^>= 17, please check your java version. + goto finally +) + +@REM ----------------------------------------------------------------------------- +@REM SET DIRS +pushd %~dp0..\.. +if NOT DEFINED IOTDB_HOME set IOTDB_HOME=%cd% +popd +if NOT DEFINED IOTDB_CONF set IOTDB_CONF=%IOTDB_HOME%\conf +set IOTDB_LOG_DIR=%IOTDB_HOME%\logs +if NOT EXIST %IOTDB_LOG_DIR% mkdir %IOTDB_LOG_DIR% + +@REM ----------------------------------------------------------------------------- +@REM SET JVM OPTIONS +if EXIST %IOTDB_CONF%\windows\edge-env.bat ( + call %IOTDB_CONF%\windows\edge-env.bat +) else ( + echo Can't find %IOTDB_CONF%\windows\edge-env.bat + goto finally +) + +set illegal_access_params=--add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED + +set CLASSPATH=%IOTDB_HOME%\lib\* +set MAIN_CLASS=org.apache.iotdb.edge.EdgeNode + +@REM CONFIGNODE_HOME must also point to the installation directory, otherwise the +@REM ConfigNode part resolves its data directories against the working directory. +set iotdb_parms=-Dlogback.configurationFile="%IOTDB_CONF%\logback-edge.xml" +set iotdb_parms=%iotdb_parms% -DIOTDB_HOME="%IOTDB_HOME%" +set iotdb_parms=%iotdb_parms% -DCONFIGNODE_HOME="%IOTDB_HOME%" +set iotdb_parms=%iotdb_parms% -DIOTDB_DATA_HOME="%IOTDB_HOME%" +set iotdb_parms=%iotdb_parms% -DTSFILE_HOME="%IOTDB_HOME%" +set iotdb_parms=%iotdb_parms% -DIOTDB_CONF="%IOTDB_CONF%" +set iotdb_parms=%iotdb_parms% -DCONFIGNODE_CONF="%IOTDB_CONF%" +set iotdb_parms=%iotdb_parms% -DTSFILE_CONF="%IOTDB_CONF%" +set iotdb_parms=%iotdb_parms% -Dname=iotdb.EdgeNode +set iotdb_parms=%iotdb_parms% -DIOTDB_LOG_DIR="%IOTDB_LOG_DIR%" +set iotdb_parms=%iotdb_parms% -DCONFIGNODE_LOG_DIR="%IOTDB_LOG_DIR%" +set iotdb_parms=%iotdb_parms% -DOFF_HEAP_MEMORY=%OFF_HEAP_MEMORY% + +@REM ----------------------------------------------------------------------------- +@REM START +java %illegal_access_params% %iotdb_parms% %IOTDB_JMX_OPTS% -cp "%CLASSPATH%" %MAIN_CLASS% -s + +goto finally + +:finally +pause diff --git a/scripts/sbin/windows/stop-edge.bat b/scripts/sbin/windows/stop-edge.bat new file mode 100644 index 00000000000..c07917fbba4 --- /dev/null +++ b/scripts/sbin/windows/stop-edge.bat @@ -0,0 +1,23 @@ +@echo off +@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 Stopping IoTDB Edge (the merged ConfigNode + DataNode process) +powershell -NoProfile -Command "Get-CimInstance Win32_Process -Filter \"name='java.exe'\" | Where-Object { $_.CommandLine -like '*org.apache.iotdb.edge.EdgeNode*' } | ForEach-Object { Stop-Process -Id $_.ProcessId -Force; Write-Host ('IoTDB Edge process ' + $_.ProcessId + ' stopped.') }" +pause
