JackieTien97 commented on code in PR #18538:
URL: https://github.com/apache/iotdb/pull/18538#discussion_r3891349757


##########
iotdb-core/node-commons/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

Review Comment:
   Addressed within the scope of this additive distribution PR in 613de3b751 by 
removing the ineffective Edge override. The missing common-property loading 
predates this PR, so CommonDescriptor and the shared default remain unchanged; 
fixing that shared behavior can be handled separately. The inference executor 
creates workers lazily, rather than eagerly creating five workers during 
startup. The packaged-configuration IT now checks that Edge does not advertise 
this ineffective override.



##########
distribution/src/assembly/edge.xml:
##########
@@ -0,0 +1,146 @@
+<?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.
+
+-->
+<assembly>
+    <id>edge-bin</id>
+    <formats>
+        <format>dir</format>
+        <format>zip</format>
+    </formats>
+    <baseDirectory>apache-iotdb-${project.version}-edge-bin</baseDirectory>

Review Comment:
   Updated the PR description to use apache-iotdb-${version}-edge-bin 
consistently in Motivation and Packaging, matching edge.xml, the POM, READMEs, 
and IT. Also refreshed the Edge configuration source paths and validation 
description. The assembly name itself is unchanged.



##########
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"/>

Review Comment:
   Fixed in 613de3b751, including the same issue for PIPE. Removed the 
undefined appender references while retaining the INFO logger levels and 
default additivity, so query-frequency and Pipe messages continue through the 
existing root appenders. The packaged-configuration IT checks that every 
remaining appender-ref resolves to a defined appender.



##########
iotdb-core/confignode/src/main/java/org/apache/iotdb/edge/EdgeNode.java:
##########
@@ -0,0 +1,120 @@
+/*
+ * 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;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * 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 AtomicReference<Throwable> configNodeError = new AtomicReference<>();
+    Thread configNodeThread =
+        new Thread(
+            () -> {
+              try {
+                ConfigNode.main(new String[] {"-s"});
+              } catch (Throwable t) {
+                configNodeError.set(t);
+              }
+            },
+            "EdgeNode-ConfigNode-Bootstrap");
+    configNodeThread.start();
+
+    int internalPort = 
ConfigNodeDescriptor.getInstance().getConf().getInternalPort();
+    waitPortOpen(internalPort, configNodeError);
+    throwIfConfigNodeBootstrapFailed(configNodeError);
+    Thread.sleep(LEADER_ELECTION_GRACE_MS);
+    throwIfConfigNodeBootstrapFailed(configNodeError);
+    
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 
throwIfConfigNodeBootstrapFailed(AtomicReference<Throwable> configNodeError) {
+    Throwable error = configNodeError.get();
+    if (error != null) {
+      throw new IllegalStateException(
+          
ConfigNodeMessages.EXCEPTION_IOTDB_EDGE_CONFIGNODE_BOOTSTRAP_FAILED_02EEE59A, 
error);
+    }
+  }
+
+  private static void waitPortOpen(int port, AtomicReference<Throwable> 
configNodeError)
+      throws InterruptedException {
+    long deadline = System.currentTimeMillis() + CONFIG_NODE_READY_TIMEOUT_MS;
+    while (System.currentTimeMillis() < deadline) {
+      if (configNodeError.get() != null) {
+        return;
+      }
+      try (Socket socket = new Socket()) {
+        socket.connect(new InetSocketAddress("127.0.0.1", port), 1000);

Review Comment:
   Fixed in 613de3b751. The readiness probe now uses 
ConfigNodeConfig.getInternalAddress() together with the configured internal 
port. IoTDBEdgeBasicIT accepts EdgeConfigNodeAddress, and the Linux workflow 
uses 127.0.0.2 to exercise this regression. The packaged IT also passed locally 
with both the default address and a non-loopback local address.



##########
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

Review Comment:
   Fixed in 613de3b751. edge-env.bat loads windows/iotdb-common.bat and appends 
TSFILE_LOCALE_JVM_OPT in a separate command, so expansion occurs after CALL has 
set the value. Windows launcher regression coverage checks both the 
empty/default and Chinese filtered values, including clearing an inherited 
stale locale option. Standard Windows node environment scripts are unchanged.



##########
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

Review Comment:
   Fixed in 613de3b751. The Edge-only check-edge.ps1 helper reads all seven 
configured service/consensus ports, falls back to their existing defaults when 
omitted, and rejects occupied or invalid ports before launching EdgeNode. 
start-edge.bat honors IOTDB_CONF and quoted paths and propagates failures as a 
nonzero exit code. The Windows workflow covers each occupied port separately, 
custom configuration, paths with spaces, defaults, comments/duplicate 
properties, and invalid values. The helper is included only in the Edge 
package; all five existing distributions retain identical file lists, modes, 
and non-JAR contents compared with the pre-fix PR head.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to