This is an automated email from the ASF dual-hosted git repository.

imbajin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hugegraph.git


The following commit(s) were added to refs/heads/master by this push:
     new c10779dc6 feat(server): support build & use(RocksDB) on RISC-V (#3102)
c10779dc6 is described below

commit c10779dc6d8c4537a5bbbeb862b9e09d34004ba8
Author: Sean <[email protected]>
AuthorDate: Sat Jul 25 13:45:19 2026 +0800

    feat(server): support build & use(RocksDB) on RISC-V (#3102)
    
    - Address the HugeGraph Server + RocksDB `linux/riscv64` build and minimum 
runtime
      support tracked by #3099.
    - Keep the change isolated from the existing Docker image design and from 
the JDK,
      build, and test paths used by other architectures.
    
    ---------
    
    Co-authored-by: Sean <[email protected]>
---
 .github/workflows/riscv64-ci.yml                   | 126 ++++++++++++++
 .github/workflows/server-ci.yml                    |   5 +
 hugegraph-pd/hg-pd-grpc/pom.xml                    |  37 +++-
 hugegraph-server/README.md                         |  43 +++++
 hugegraph-server/hugegraph-core/pom.xml            |  24 ++-
 hugegraph-server/hugegraph-dist/pom.xml            | 123 ++++++++-----
 .../src/assembly/static/bin/dump-store.sh          |  12 +-
 .../src/assembly/static/bin/hugegraph-server.sh    |   2 +
 .../src/assembly/static/bin/init-store.sh          |   1 +
 .../src/assembly/static/bin/stop-hugegraph.sh      |   6 +-
 .../hugegraph-dist/src/assembly/static/bin/util.sh |  39 +++++
 .../src/assembly/travis/check-rocksdb-only-dist.sh |  97 +++++++++++
 .../src/assembly/travis/rocksdb-jni-smoke.groovy   |  55 ++++++
 .../travis/run-native-runtime-smoke-test.sh        |  91 ++++++++++
 .../assembly/travis/run-rocksdb-jni-smoke-test.sh  | 130 ++++++++++++++
 .../assembly/travis/run-server-e2e-smoke-test.sh   | 191 +++++++++++++++++++++
 .../src/main/resources/backend.properties          |   2 +-
 17 files changed, 933 insertions(+), 51 deletions(-)

diff --git a/.github/workflows/riscv64-ci.yml b/.github/workflows/riscv64-ci.yml
new file mode 100644
index 000000000..9f8ca1205
--- /dev/null
+++ b/.github/workflows/riscv64-ci.yml
@@ -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.
+#
+
+name: "RISC-V Server CI"
+
+on:
+  workflow_call:
+
+permissions:
+  contents: read
+
+env:
+  BINFMT_IMAGE: >-
+    
tonistiigi/binfmt@sha256:400a4873b838d1b89194d982c45e5fb3cda4593fbfd7e08a02e76b03b21166f0
+  RISCV64_BASE_IMAGE: >-
+    
ubuntu@sha256:4edded5722eb644868b7b976033d241d2ab3fff0a170924df69b200a59a2b994
+  DRAGONWELL_RISCV64_ARCHIVE: >-
+    Alibaba_Dragonwell_Extended_11.0.31.28.11_riscv64_linux.tar.gz
+  DRAGONWELL_RISCV64_SHA256: >-
+    7df2d308f0dca7a779d2854e6da19214f99cd77aa6d4982c3bf981a77266a79b
+  DRAGONWELL_RISCV64_URL: >-
+    
https://github.com/dragonwell-project/dragonwell11/releases/download/dragonwell-extended-11.0.31.28_jdk-11.0.31-ga/Alibaba_Dragonwell_Extended_11.0.31.28.11_riscv64_linux.tar.gz
+  RISCV64_CONTAINER: >-
+    hugegraph-riscv64-ci-${{ github.run_id }}-${{ github.run_attempt }}
+
+jobs:
+  build-server-riscv64:
+    runs-on: ubuntu-24.04
+    timeout-minutes: 90
+
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4
+        with:
+          persist-credentials: false
+
+      - name: Start isolated RISC-V environment
+        run: |
+          docker run --privileged --rm "$BINFMT_IMAGE" --install riscv64
+          docker run --detach --init --platform linux/riscv64 \
+            --name "$RISCV64_CONTAINER" "$RISCV64_BASE_IMAGE" sleep infinity
+          test "$(docker exec "$RISCV64_CONTAINER" uname -m)" = riscv64
+
+      - name: Prepare source and Java 11
+        run: |
+          ARCHIVE_PATH="$RUNNER_TEMP/$DRAGONWELL_RISCV64_ARCHIVE"
+          curl --fail --location --retry 3 --show-error \
+            "$DRAGONWELL_RISCV64_URL" --output "$ARCHIVE_PATH"
+          echo "$DRAGONWELL_RISCV64_SHA256  $ARCHIVE_PATH" | sha256sum -c -
+
+          docker exec "$RISCV64_CONTAINER" mkdir -p /workspace /opt/dragonwell
+          git ls-files -z | tar --null --files-from=- -cf - | \
+            docker exec -i "$RISCV64_CONTAINER" tar -xf - -C /workspace
+          docker cp "$ARCHIVE_PATH" \
+            "$RISCV64_CONTAINER:/tmp/$DRAGONWELL_RISCV64_ARCHIVE"
+
+      - name: Build and smoke test on RISC-V
+        run: |
+          docker exec \
+            --env DRAGONWELL_RISCV64_ARCHIVE="$DRAGONWELL_RISCV64_ARCHIVE" \
+            --env DRAGONWELL_RISCV64_SHA256="$DRAGONWELL_RISCV64_SHA256" \
+            "$RISCV64_CONTAINER" bash -euo pipefail -c '
+              test "$(uname -m)" = riscv64
+              apt-get -q update
+              apt-get -q install -y --no-install-recommends \
+                ca-certificates curl jq libatomic1 libgcc-s1 libstdc++6 \
+                lsof maven procps \
+                protobuf-compiler protobuf-compiler-grpc-java-plugin
+
+              ARCHIVE_PATH="/tmp/$DRAGONWELL_RISCV64_ARCHIVE"
+              echo "$DRAGONWELL_RISCV64_SHA256  $ARCHIVE_PATH" | sha256sum -c -
+              tar -xzf "$ARCHIVE_PATH" --strip-components=1 -C /opt/dragonwell
+              rm "$ARCHIVE_PATH"
+              export JAVA_HOME=/opt/dragonwell
+              export PATH="$JAVA_HOME/bin:$PATH"
+
+              java -XshowSettings:vm -version
+              test -x /usr/bin/protoc
+              test -x /usr/bin/grpc_java_plugin
+
+              cd /workspace
+              MAVEN_OPTS="-XX:TieredStopAtLevel=1 -XX:ActiveProcessorCount=2" \
+                mvn clean package -B -ntp -Drocksdb-only \
+                  -P riscv64-protobuf-tools \
+                  -pl hugegraph-server/hugegraph-dist -am \
+                  -Dmaven.test.skip=true -Dmaven.javadoc.skip=true
+              
hugegraph-server/hugegraph-dist/src/assembly/travis/check-rocksdb-only-dist.sh \
+                hugegraph-server/apache-hugegraph-server-*/
+              
hugegraph-server/hugegraph-dist/src/assembly/travis/run-native-runtime-smoke-test.sh
 \
+                hugegraph-server/apache-hugegraph-server-*/
+            '
+
+      - name: Show server log on failure
+        if: failure()
+        run: |
+          if docker container inspect "$RISCV64_CONTAINER" >/dev/null 2>&1; 
then
+            docker exec "$RISCV64_CONTAINER" bash -c '
+              find /workspace -path "*/logs/hugegraph-server.log" \
+                -exec tail -n 200 {} \;
+            ' || true
+          fi
+
+      - name: Clean up RISC-V environment
+        if: always()
+        run: |
+          if docker container inspect "$RISCV64_CONTAINER" >/dev/null 2>&1; 
then
+            docker rm --force --volumes "$RISCV64_CONTAINER"
+          fi
+          if docker container inspect "$RISCV64_CONTAINER" >/dev/null 2>&1; 
then
+            echo "RISC-V CI container still exists: $RISCV64_CONTAINER" >&2
+            exit 1
+          fi
diff --git a/.github/workflows/server-ci.yml b/.github/workflows/server-ci.yml
index 586e36da4..0d6c54b51 100644
--- a/.github/workflows/server-ci.yml
+++ b/.github/workflows/server-ci.yml
@@ -203,3 +203,8 @@ jobs:
           if [ -f "$SERVER_DIR/bin/pid" ]; then
             $TRAVIS_DIR/stop-server.sh $SERVER_DIR || true
           fi
+
+  build-server-riscv64:
+    uses: ./.github/workflows/riscv64-ci.yml
+    permissions:
+      contents: read
diff --git a/hugegraph-pd/hg-pd-grpc/pom.xml b/hugegraph-pd/hg-pd-grpc/pom.xml
index 7df8622e1..be8ccc44f 100644
--- a/hugegraph-pd/hg-pd-grpc/pom.xml
+++ b/hugegraph-pd/hg-pd-grpc/pom.xml
@@ -32,7 +32,7 @@
 
 
     <properties>
-        <os.plugin.version>1.6.0</os.plugin.version>
+        <os.plugin.version>1.7.1</os.plugin.version>
         <grpc.version>1.39.0</grpc.version>
         <protoc.version>3.17.2</protoc.version>
         <protobuf.plugin.version>0.6.1</protobuf.plugin.version>
@@ -127,4 +127,39 @@
             </plugin>
         </plugins>
     </build>
+
+    <profiles>
+        <profile>
+            <id>riscv64-protobuf-tools</id>
+            <activation>
+                <os>
+                    <arch>riscv64</arch>
+                </os>
+            </activation>
+            <properties>
+                <!-- Compatible with the distro generators and Server runtime 
-->
+                <grpc.version>1.47.0</grpc.version>
+                
<riscv64.protobuf.java.version>3.21.7</riscv64.protobuf.java.version>
+            </properties>
+            <dependencies>
+                <dependency>
+                    <groupId>com.google.protobuf</groupId>
+                    <artifactId>protobuf-java</artifactId>
+                    <version>${riscv64.protobuf.java.version}</version>
+                </dependency>
+            </dependencies>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.xolstice.maven.plugins</groupId>
+                        <artifactId>protobuf-maven-plugin</artifactId>
+                        <configuration>
+                            
<protocExecutable>/usr/bin/protoc</protocExecutable>
+                            
<pluginExecutable>/usr/bin/grpc_java_plugin</pluginExecutable>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
 </project>
diff --git a/hugegraph-server/README.md b/hugegraph-server/README.md
index c145190bf..ef6c9f111 100644
--- a/hugegraph-server/README.md
+++ b/hugegraph-server/README.md
@@ -30,3 +30,46 @@ HUGEGRAPH_VERSION=1.7.0 docker compose -f 
docker-compose-3pd-3store-3server.yml
 ```
 
 See [docker/README.md](../docker/README.md) for the full setup guide.
+
+## RISC-V Development and Testing
+
+The end-to-end RISC-V CI validation currently runs on 64-bit `linux/riscv64` 
LP64D with
+Ubuntu 24.04 and glibc 2.39. It covers HugeGraph Server and the embedded 
RocksDB backend.
+PD, Store, HStore, other backends, musl/Alpine, and 32-bit RISC-V are out of 
scope.
+
+The dedicated [RISC-V Server CI](../.github/workflows/riscv64-ci.yml) runs a 
RocksDB-only
+native build and runtime smoke test in an isolated QEMU environment. It uses 
the
+checksum-pinned Alibaba Dragonwell 11 Extended Server VM and installs 
`libatomic1` for the
+packaged RocksDB JNI library. QEMU is for correctness testing and is not a 
performance
+benchmark.
+
+The packaged `rocksdbjni:8.10.2` RISC-V ELF references glibc symbols through
+`GLIBC_2.30`. This is an inferred minimum for that JNI artifact only, not a 
validated
+compatibility floor for the complete HugeGraph, Dragonwell, and system-library 
runtime.
+
+The repository Dockerfile and published HugeGraph image do not include RISC-V 
support.
+Image publication requires separate multi-architecture design and validation.
+
+For the same validation on a native Debian-derived RISC-V system, use 
Dragonwell 11
+Extended `11.0.31.28.11` with the archive checksum declared in the CI 
workflow, then
+install the build and runtime dependencies:
+
+```bash
+sudo apt-get update
+sudo apt-get install -y ca-certificates curl jq libatomic1 libgcc-s1 
libstdc++6 \
+  lsof maven procps protobuf-compiler protobuf-compiler-grpc-java-plugin
+```
+
+After selecting Dragonwell as `JAVA_HOME`, build and verify the RocksDB-only 
distribution:
+
+```bash
+test "$(uname -m)" = riscv64
+"$JAVA_HOME/bin/java" -XshowSettings:vm -version
+mvn clean package -Drocksdb-only -pl hugegraph-server/hugegraph-dist -am \
+  -P riscv64-protobuf-tools \
+  -Dmaven.test.skip=true -Dmaven.javadoc.skip=true
+hugegraph-server/hugegraph-dist/src/assembly/travis/check-rocksdb-only-dist.sh 
\
+  hugegraph-server/apache-hugegraph-server-*/
+hugegraph-server/hugegraph-dist/src/assembly/travis/run-native-runtime-smoke-test.sh
 \
+  hugegraph-server/apache-hugegraph-server-*/
+```
diff --git a/hugegraph-server/hugegraph-core/pom.xml 
b/hugegraph-server/hugegraph-core/pom.xml
index 233449632..14f5274cb 100644
--- a/hugegraph-server/hugegraph-core/pom.xml
+++ b/hugegraph-server/hugegraph-core/pom.xml
@@ -335,7 +335,7 @@
             <extension>
                 <groupId>kr.motd.maven</groupId>
                 <artifactId>os-maven-plugin</artifactId>
-                <version>1.5.0.Final</version>
+                <version>1.7.1</version>
             </extension>
         </extensions>
 
@@ -408,4 +408,26 @@
             </plugin>
         </plugins>
     </build>
+
+    <profiles>
+        <profile>
+            <id>riscv64-protobuf-tools</id>
+            <activation>
+                <os>
+                    <arch>riscv64</arch>
+                </os>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.xolstice.maven.plugins</groupId>
+                        <artifactId>protobuf-maven-plugin</artifactId>
+                        <configuration>
+                            
<protocExecutable>/usr/bin/protoc</protocExecutable>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
 </project>
diff --git a/hugegraph-server/hugegraph-dist/pom.xml 
b/hugegraph-server/hugegraph-dist/pom.xml
index 5914b038b..430a21390 100644
--- a/hugegraph-server/hugegraph-dist/pom.xml
+++ b/hugegraph-server/hugegraph-dist/pom.xml
@@ -34,6 +34,8 @@
         
<assembly.descriptor.dir>${assembly.dir}/descriptor</assembly.descriptor.dir>
         <assembly.static.dir>${assembly.dir}/static</assembly.static.dir>
         <jansi.version>2.4.0</jansi.version>
+        <jamm.version>0.3.2</jamm.version>
+        <hugegraph.backends>rocksdb, hbase, hstore</hugegraph.backends>
     </properties>
 
     <dependencies>
@@ -59,53 +61,11 @@
                 </exclusion>
             </exclusions>
         </dependency>
-        <dependency>
-            <groupId>org.apache.hugegraph</groupId>
-            <artifactId>hugegraph-cassandra</artifactId>
-            <version>${revision}</version>
-            <exclusions>
-                <exclusion>
-                    <artifactId>metrics-core</artifactId>
-                    <groupId>io.dropwizard.metrics</groupId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.hugegraph</groupId>
-            <artifactId>hugegraph-scylladb</artifactId>
-            <version>${revision}</version>
-        </dependency>
         <dependency>
             <groupId>org.apache.hugegraph</groupId>
             <artifactId>hugegraph-rocksdb</artifactId>
             <version>${revision}</version>
         </dependency>
-        <dependency>
-            <groupId>org.apache.hugegraph</groupId>
-            <artifactId>hugegraph-mysql</artifactId>
-            <version>${revision}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.hugegraph</groupId>
-            <artifactId>hugegraph-palo</artifactId>
-            <version>${revision}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.hugegraph</groupId>
-            <artifactId>hugegraph-hbase</artifactId>
-            <version>${revision}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.hugegraph</groupId>
-            <artifactId>hugegraph-postgresql</artifactId>
-            <version>${revision}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.hugegraph</groupId>
-            <artifactId>hugegraph-hstore</artifactId>
-            <version>${revision}</version>
-        </dependency>
-
         <dependency>
             <groupId>org.apache.tinkerpop</groupId>
             <artifactId>gremlin-console</artifactId>
@@ -133,6 +93,13 @@
             <version>${jansi.version}</version>
             <scope>runtime</scope>
         </dependency>
+        <!-- Required by the -javaagent option in bin/gremlin-console.sh -->
+        <dependency>
+            <groupId>com.github.jbellis</groupId>
+            <artifactId>jamm</artifactId>
+            <version>${jamm.version}</version>
+            <scope>runtime</scope>
+        </dependency>
     </dependencies>
 
     <build>
@@ -144,6 +111,16 @@
             <resource>
                 <directory>${basedir}/src/main/resources</directory>
                 <filtering>false</filtering>
+                <excludes>
+                    <exclude>backend.properties</exclude>
+                </excludes>
+            </resource>
+            <resource>
+                <directory>${basedir}/src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>backend.properties</include>
+                </includes>
             </resource>
         </resources>
 
@@ -289,6 +266,68 @@
     </build>
 
     <profiles>
+        <profile>
+            <id>rocksdb-only</id>
+            <activation>
+                <property>
+                    <name>rocksdb-only</name>
+                </property>
+            </activation>
+            <properties>
+                <hugegraph.backends>rocksdb</hugegraph.backends>
+            </properties>
+        </profile>
+        <profile>
+            <id>all-backends</id>
+            <activation>
+                <property>
+                    <name>!rocksdb-only</name>
+                </property>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>org.apache.hugegraph</groupId>
+                    <artifactId>hugegraph-cassandra</artifactId>
+                    <version>${revision}</version>
+                    <exclusions>
+                        <exclusion>
+                            <artifactId>metrics-core</artifactId>
+                            <groupId>io.dropwizard.metrics</groupId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.hugegraph</groupId>
+                    <artifactId>hugegraph-scylladb</artifactId>
+                    <version>${revision}</version>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.hugegraph</groupId>
+                    <artifactId>hugegraph-mysql</artifactId>
+                    <version>${revision}</version>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.hugegraph</groupId>
+                    <artifactId>hugegraph-palo</artifactId>
+                    <version>${revision}</version>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.hugegraph</groupId>
+                    <artifactId>hugegraph-hbase</artifactId>
+                    <version>${revision}</version>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.hugegraph</groupId>
+                    <artifactId>hugegraph-postgresql</artifactId>
+                    <version>${revision}</version>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.hugegraph</groupId>
+                    <artifactId>hugegraph-hstore</artifactId>
+                    <version>${revision}</version>
+                </dependency>
+            </dependencies>
+        </profile>
         <profile>
             <id>assembly-hugegraph</id>
             <build>
diff --git 
a/hugegraph-server/hugegraph-dist/src/assembly/static/bin/dump-store.sh 
b/hugegraph-server/hugegraph-dist/src/assembly/static/bin/dump-store.sh
index 425ad9f15..14b6ac1f7 100755
--- a/hugegraph-server/hugegraph-dist/src/assembly/static/bin/dump-store.sh
+++ b/hugegraph-server/hugegraph-dist/src/assembly/static/bin/dump-store.sh
@@ -30,16 +30,20 @@ TOP="$(cd $BIN/../ && pwd)"
 CONF=$TOP/conf
 LIB=$TOP/lib
 
+. "${BIN}"/util.sh
+
+configure_riscv64_libatomic || exit 1
+
 if [ -n "$JAVA_HOME" ]; then
     JAVA="$JAVA_HOME"/bin/java
 else
     JAVA=java
 fi
 
-conf=$1
 if [ $# -eq 0 ]; then
-    conf=$CONF/hugegraph.properties
+    set -- "$CONF/graphs/hugegraph.properties"
 fi
+conf=$1
 
 cd $TOP
 
@@ -47,5 +51,5 @@ echo "Dumping HugeGraph Store($conf)..."
 
 dump_store_ext_jar_path=$LIB/hugegraph-dist-*.jar
 for i in $LIB/*.jar; do dump_store_ext_jar_path=$dump_store_ext_jar_path:$i;  
export dump_store_ext_jar_path; done
-exec $JAVA -cp dump_store_ext_jar_path \
-org.apache.hugegraph.cmd.StoreDumper $conf $2 $3 $4
+exec "$JAVA" -cp "$dump_store_ext_jar_path" \
+org.apache.hugegraph.cmd.StoreDumper "$@"
diff --git 
a/hugegraph-server/hugegraph-dist/src/assembly/static/bin/hugegraph-server.sh 
b/hugegraph-server/hugegraph-dist/src/assembly/static/bin/hugegraph-server.sh
index c5f84d493..3915a5f63 100644
--- 
a/hugegraph-server/hugegraph-dist/src/assembly/static/bin/hugegraph-server.sh
+++ 
b/hugegraph-server/hugegraph-dist/src/assembly/static/bin/hugegraph-server.sh
@@ -45,6 +45,8 @@ GITHUB="https://github.com";
 export HUGEGRAPH_HOME="$TOP"
 . "${BIN}"/util.sh
 
+configure_riscv64_libatomic || exit 1
+
 # Parse the server arguments in array way
 SERVER_ARGS=("$@")
 GREMLIN_SERVER_CONF="${SERVER_ARGS[0]:-}"
diff --git 
a/hugegraph-server/hugegraph-dist/src/assembly/static/bin/init-store.sh 
b/hugegraph-server/hugegraph-dist/src/assembly/static/bin/init-store.sh
index 9aefd1160..b9da84166 100755
--- a/hugegraph-server/hugegraph-dist/src/assembly/static/bin/init-store.sh
+++ b/hugegraph-server/hugegraph-dist/src/assembly/static/bin/init-store.sh
@@ -33,6 +33,7 @@ PLUGINS="$TOP/plugins"
 
 . "${BIN}"/util.sh
 
+configure_riscv64_libatomic || exit 1
 ensure_path_writable "${PLUGINS}"
 
 if [[ -n "$JAVA_HOME" ]]; then
diff --git 
a/hugegraph-server/hugegraph-dist/src/assembly/static/bin/stop-hugegraph.sh 
b/hugegraph-server/hugegraph-dist/src/assembly/static/bin/stop-hugegraph.sh
index 740774634..c63035e07 100755
--- a/hugegraph-server/hugegraph-dist/src/assembly/static/bin/stop-hugegraph.sh
+++ b/hugegraph-server/hugegraph-dist/src/assembly/static/bin/stop-hugegraph.sh
@@ -63,6 +63,8 @@ fi
 
 PID=$(cat $PID_FILE)
 
-if kill_process_and_wait "HugeGraphServer" "$PID" 
"$SERVER_SHUTDOWN_TIMEOUT_S"; then
-    rm "$PID_FILE"
+if ! kill_process_and_wait "HugeGraphServer" "$PID" 
"$SERVER_SHUTDOWN_TIMEOUT_S"; then
+    exit 1
 fi
+
+rm "$PID_FILE"
diff --git a/hugegraph-server/hugegraph-dist/src/assembly/static/bin/util.sh 
b/hugegraph-server/hugegraph-dist/src/assembly/static/bin/util.sh
index e2655c69d..91c0c3efb 100755
--- a/hugegraph-server/hugegraph-dist/src/assembly/static/bin/util.sh
+++ b/hugegraph-server/hugegraph-dist/src/assembly/static/bin/util.sh
@@ -25,6 +25,45 @@ function command_available() {
     fi
 }
 
+function configure_riscv64_libatomic() {
+    if [[ "$(uname -s)" != "Linux" || "$(uname -m)" != "riscv64" ]]; then
+        return 0
+    fi
+
+    if [[ "${LD_PRELOAD:-}" == *"libatomic.so.1"* ]]; then
+        return 0
+    fi
+
+    local libatomic=""
+    if command_available "ldconfig"; then
+        libatomic=$(ldconfig -p 2>/dev/null | \
+                    awk '/libatomic\.so\.1 .*=>/ && !path {path=$NF}
+                         END {if (path) print path}')
+    fi
+
+    if [[ -z "$libatomic" ]]; then
+        local candidate
+        for candidate in /lib/riscv64-linux-gnu/libatomic.so.1 \
+                         /usr/lib/riscv64-linux-gnu/libatomic.so.1 \
+                         /lib64/lp64d/libatomic.so.1 \
+                         /usr/lib64/lp64d/libatomic.so.1 \
+                         /lib64/libatomic.so.1 \
+                         /usr/lib64/libatomic.so.1; do
+            if [[ -r "$candidate" ]]; then
+                libatomic="$candidate"
+                break
+            fi
+        done
+    fi
+
+    if [[ -z "$libatomic" ]]; then
+        echo "RISC-V RocksDB requires libatomic.so.1; install libatomic1" >&2
+        return 1
+    fi
+
+    export LD_PRELOAD="${LD_PRELOAD:+${LD_PRELOAD}:}${libatomic}"
+}
+
 # read a property from .properties file
 function read_property() {
     # file path
diff --git 
a/hugegraph-server/hugegraph-dist/src/assembly/travis/check-rocksdb-only-dist.sh
 
b/hugegraph-server/hugegraph-dist/src/assembly/travis/check-rocksdb-only-dist.sh
new file mode 100755
index 000000000..133739422
--- /dev/null
+++ 
b/hugegraph-server/hugegraph-dist/src/assembly/travis/check-rocksdb-only-dist.sh
@@ -0,0 +1,97 @@
+#!/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.
+#
+
+set -euo pipefail
+
+if [[ $# -ne 1 ]]; then
+    echo "USAGE: $0 SERVER_DIR" >&2
+    exit 1
+fi
+
+SERVER_DIR=$1
+LIB_DIR="$SERVER_DIR/lib"
+DIST_JAR=""
+WORK_DIR=$(mktemp -d "${TMPDIR:-/tmp}/hugegraph-dist-check.XXXXXX")
+
+cleanup() {
+    rm -rf "$WORK_DIR"
+}
+trap cleanup EXIT
+
+if [[ ! -d "$LIB_DIR" ]]; then
+    echo "Distribution lib directory does not exist: $LIB_DIR" >&2
+    exit 1
+fi
+
+function require_jar() {
+    local pattern=$1
+    if ! find "$LIB_DIR" -maxdepth 1 -type f -name "$pattern" -print -quit | 
grep -q .; then
+        echo "Missing required RocksDB distribution artifact: $pattern" >&2
+        exit 1
+    fi
+}
+
+function forbid_jar() {
+    local pattern=$1
+    local match
+    match=$(find "$LIB_DIR" -maxdepth 1 -type f -name "$pattern" -print -quit)
+    if [[ -n "$match" ]]; then
+        echo "Unrelated backend artifact found in RocksDB-only distribution: 
$match" >&2
+        exit 1
+    fi
+}
+
+for pattern in hugegraph-core-*.jar \
+               hugegraph-api-*.jar \
+               hugegraph-rocksdb-*.jar \
+               hugegraph-dist-*.jar \
+               jamm-*.jar \
+               rocksdbjni-*.jar; do
+    require_jar "$pattern"
+done
+
+DIST_JAR=$(find "$LIB_DIR" -maxdepth 1 -type f \
+                -name 'hugegraph-dist-*.jar' -print -quit)
+DIST_JAR=$(cd "$(dirname "$DIST_JAR")" && pwd)/$(basename "$DIST_JAR")
+if command -v unzip >/dev/null 2>&1; then
+    BACKEND_PROPERTIES=$(unzip -p "$DIST_JAR" backend.properties)
+elif command -v jar >/dev/null 2>&1; then
+    (cd "$WORK_DIR" && jar xf "$DIST_JAR" backend.properties)
+    BACKEND_PROPERTIES=$(cat "$WORK_DIR/backend.properties")
+else
+    echo "The distribution check requires unzip or a JDK jar command" >&2
+    exit 1
+fi
+
+if ! grep -qx 'backends=\[rocksdb\]' <<< "$BACKEND_PROPERTIES"; then
+    echo "RocksDB-only distribution has an invalid backend registry" >&2
+    printf '%s\n' "$BACKEND_PROPERTIES" >&2
+    exit 1
+fi
+
+for pattern in hugegraph-cassandra-*.jar \
+               hugegraph-scylladb-*.jar \
+               hugegraph-mysql-*.jar \
+               hugegraph-palo-*.jar \
+               hugegraph-hbase-*.jar \
+               hugegraph-postgresql-*.jar \
+               hugegraph-hstore-*.jar; do
+    forbid_jar "$pattern"
+done
+
+echo "RocksDB-only distribution contains the required backend and no unrelated 
backend JARs"
diff --git 
a/hugegraph-server/hugegraph-dist/src/assembly/travis/rocksdb-jni-smoke.groovy 
b/hugegraph-server/hugegraph-dist/src/assembly/travis/rocksdb-jni-smoke.groovy
new file mode 100644
index 000000000..1baa856bf
--- /dev/null
+++ 
b/hugegraph-server/hugegraph-dist/src/assembly/travis/rocksdb-jni-smoke.groovy
@@ -0,0 +1,55 @@
+//
+// 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.
+//
+
+import java.nio.charset.StandardCharsets
+import java.util.Arrays
+
+import org.rocksdb.Options
+import org.rocksdb.RocksDB
+
+rocksdbSmokePath = System.getenv('ROCKSDB_SMOKE_DIR')
+if (!rocksdbSmokePath) {
+    throw new IllegalArgumentException('ROCKSDB_SMOKE_DIR is required')
+}
+
+rocksdbSmokeKey = 'hugegraph-riscv64-key'.getBytes(StandardCharsets.UTF_8)
+rocksdbSmokeExpected = 
'hugegraph-riscv64-value'.getBytes(StandardCharsets.UTF_8)
+
+RocksDB.loadLibrary()
+
+rocksdbSmokeOptions = new Options().setCreateIfMissing(true)
+rocksdbSmokeDb = null
+try {
+    rocksdbSmokeDb = RocksDB.open(rocksdbSmokeOptions, rocksdbSmokePath)
+    rocksdbSmokeDb.put(rocksdbSmokeKey, rocksdbSmokeExpected)
+    def actual = rocksdbSmokeDb.get(rocksdbSmokeKey)
+    if (!Arrays.equals(rocksdbSmokeExpected, actual)) {
+        throw new IllegalStateException('RocksDB value differs after put/get')
+    }
+    rocksdbSmokeDb.close()
+    rocksdbSmokeDb = null
+
+    rocksdbSmokeDb = RocksDB.open(rocksdbSmokeOptions, rocksdbSmokePath)
+    actual = rocksdbSmokeDb.get(rocksdbSmokeKey)
+    if (!Arrays.equals(rocksdbSmokeExpected, actual)) {
+        throw new IllegalStateException('RocksDB value differs after reopen')
+    }
+    println('rocksdb-jni-smoke-ok')
+} finally {
+    rocksdbSmokeDb?.close()
+    rocksdbSmokeOptions.close()
+}
diff --git 
a/hugegraph-server/hugegraph-dist/src/assembly/travis/run-native-runtime-smoke-test.sh
 
b/hugegraph-server/hugegraph-dist/src/assembly/travis/run-native-runtime-smoke-test.sh
new file mode 100755
index 000000000..7cf09e30e
--- /dev/null
+++ 
b/hugegraph-server/hugegraph-dist/src/assembly/travis/run-native-runtime-smoke-test.sh
@@ -0,0 +1,91 @@
+#!/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.
+#
+set -euo pipefail
+
+if [[ $# -ne 1 ]]; then
+    echo "USAGE: $0 SERVER_DIR" >&2
+    exit 1
+fi
+
+TRAVIS_DIR=$(cd "$(dirname "$0")" && pwd)
+SERVER_DIR=$(cd "$1" && pwd)
+SERVER_URL=${SERVER_URL:-http://127.0.0.1:8080}
+EXPECTED_ARCH=${EXPECTED_ARCH:-riscv64}
+EXPECTED_JAVA_MAJOR=${EXPECTED_JAVA_MAJOR:-11}
+SERVER_START_ATTEMPTED=false
+SERVER_STARTUP_TIMEOUT=${SERVER_STARTUP_TIMEOUT:-300}
+SERVER_START_COMMAND_TIMEOUT=$((SERVER_STARTUP_TIMEOUT + 30))
+STORE_DUMP_TIMEOUT=${STORE_DUMP_TIMEOUT:-120}
+WORK_DIR=$(mktemp -d "${TMPDIR:-/tmp}/hugegraph-native-runtime-smoke.XXXXXX")
+RUN_ID="$(date +%s)_$$"
+
+export EXPECTED_ARCH EXPECTED_JAVA_MAJOR
+
+cleanup() {
+    local status=$?
+    trap - EXIT
+    if [[ "$SERVER_START_ATTEMPTED" == "true" ]]; then
+        "$SERVER_DIR/bin/stop-hugegraph.sh" -m false >/dev/null 2>&1 || 
status=1
+    fi
+    rm -rf "$WORK_DIR"
+    exit "$status"
+}
+trap cleanup EXIT
+
+start_server() {
+    if ! command -v timeout >/dev/null 2>&1; then
+        echo "Required command is unavailable: timeout" >&2
+        return 1
+    fi
+    timeout --foreground --kill-after=15s \
+            "${SERVER_START_COMMAND_TIMEOUT}s" \
+            "$SERVER_DIR/bin/start-hugegraph.sh" -t "$SERVER_STARTUP_TIMEOUT"
+}
+
+"$TRAVIS_DIR/run-rocksdb-jni-smoke-test.sh" "$SERVER_DIR"
+
+"$SERVER_DIR/bin/init-store.sh"
+SERVER_START_ATTEMPTED=true
+start_server
+"$TRAVIS_DIR/run-server-e2e-smoke-test.sh" "$SERVER_URL" create "$RUN_ID" | \
+    tee "$WORK_DIR/create.log"
+grep -q '^server-e2e-smoke-create-ok$' "$WORK_DIR/create.log"
+
+"$SERVER_DIR/bin/stop-hugegraph.sh" -m false
+timeout --foreground --kill-after=15s "${STORE_DUMP_TIMEOUT}s" \
+        "$SERVER_DIR/bin/dump-store.sh" | tee "$WORK_DIR/store-dump.log"
+grep -q 'Dump table VERTEX (offset 0 limit 20):' "$WORK_DIR/store-dump.log"
+grep -Fq "riscv-smoke-v1-$RUN_ID" "$WORK_DIR/store-dump.log"
+grep -Fq "riscv-smoke-v2-$RUN_ID" "$WORK_DIR/store-dump.log"
+echo "store-dump-smoke-ok"
+
+start_server
+"$TRAVIS_DIR/run-server-e2e-smoke-test.sh" "$SERVER_URL" verify "$RUN_ID" | \
+    tee "$WORK_DIR/verify.log"
+grep -q '^server-e2e-smoke-verify-ok$' "$WORK_DIR/verify.log"
+
+if [[ -d "$SERVER_DIR/logs" ]] && \
+   grep -Eirq 'undefined 
symbol|UnsatisfiedLinkError|UnsupportedClassVersionError|NoClassDefFoundError' \
+        "$SERVER_DIR/logs"; then
+    echo "Native linkage or Java compatibility error found in 
$SERVER_DIR/logs" >&2
+    grep -Eirn 'undefined 
symbol|UnsatisfiedLinkError|UnsupportedClassVersionError|NoClassDefFoundError' \
+        "$SERVER_DIR/logs" >&2
+    exit 1
+fi
+
+echo "native-runtime-smoke-ok"
diff --git 
a/hugegraph-server/hugegraph-dist/src/assembly/travis/run-rocksdb-jni-smoke-test.sh
 
b/hugegraph-server/hugegraph-dist/src/assembly/travis/run-rocksdb-jni-smoke-test.sh
new file mode 100755
index 000000000..5603431d5
--- /dev/null
+++ 
b/hugegraph-server/hugegraph-dist/src/assembly/travis/run-rocksdb-jni-smoke-test.sh
@@ -0,0 +1,130 @@
+#!/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.
+#
+set -euo pipefail
+
+if [[ $# -ne 1 ]]; then
+    echo "USAGE: $0 SERVER_DIR" >&2
+    exit 1
+fi
+
+TRAVIS_DIR=$(cd "$(dirname "$0")" && pwd)
+SERVER_DIR=$(cd "$1" && pwd)
+EXPECTED_ARCH=${EXPECTED_ARCH:-}
+EXPECTED_JAVA_MAJOR=${EXPECTED_JAVA_MAJOR:-11}
+ACTUAL_ARCH=$(uname -m)
+
+if [[ -n "${JAVA_HOME:-}" ]]; then
+    JAVA_CMD="$JAVA_HOME/bin/java"
+else
+    JAVA_CMD=$(command -v java || true)
+fi
+if [[ -z "$JAVA_CMD" || ! -x "$JAVA_CMD" ]]; then
+    echo "Java executable is unavailable: ${JAVA_CMD:-not found}" >&2
+    exit 1
+fi
+
+if [[ -n "$EXPECTED_ARCH" && "$ACTUAL_ARCH" != "$EXPECTED_ARCH" ]]; then
+    echo "Expected architecture $EXPECTED_ARCH, got $ACTUAL_ARCH" >&2
+    exit 1
+fi
+
+JAVA_VERSION=$("$JAVA_CMD" -version 2>&1 | \
+               awk -F '"' '/version/ {print $2; exit}')
+JAVA_MAJOR=${JAVA_VERSION%%.*}
+if [[ "$JAVA_MAJOR" == "1" ]]; then
+    JAVA_MAJOR=$(echo "$JAVA_VERSION" | cut -d. -f2)
+fi
+if [[ "$JAVA_MAJOR" != "$EXPECTED_JAVA_MAJOR" ]]; then
+    echo "Expected Java $EXPECTED_JAVA_MAJOR, got $JAVA_VERSION" >&2
+    exit 1
+fi
+
+JAVA_PROPERTIES=$("$JAVA_CMD" -XshowSettings:properties -version 2>&1)
+java_property() {
+    local key=$1
+    awk -F ' = ' -v key="$key" '{
+        name = $1
+        sub(/^[[:space:]]*/, "", name)
+        if (name == key) {
+            print $2
+            exit
+        }
+    }' <<< "$JAVA_PROPERTIES"
+}
+
+JAVA_VM_NAME=$(java_property java.vm.name)
+JAVA_VM_VENDOR=$(java_property java.vm.vendor)
+JAVA_VM_VERSION=$(java_property java.vm.version)
+JAVA_VM_INFO=$(java_property java.vm.info)
+
+if [[ -z "$JAVA_VM_NAME" || -z "$JAVA_VM_VENDOR" || -z "$JAVA_VM_INFO" ]]; then
+    echo "Failed to read Java VM properties" >&2
+    exit 1
+fi
+
+echo "Architecture: $ACTUAL_ARCH"
+echo "Java: $JAVA_VERSION"
+echo "Java VM: $JAVA_VM_NAME ($JAVA_VM_VENDOR, $JAVA_VM_VERSION, 
$JAVA_VM_INFO)"
+if command -v getconf >/dev/null 2>&1; then
+    echo "C library: $(getconf GNU_LIBC_VERSION 2>/dev/null || echo unknown)"
+fi
+
+. "$SERVER_DIR/bin/util.sh"
+configure_riscv64_libatomic
+
+if [[ "$ACTUAL_ARCH" == "riscv64" ]]; then
+    EXPECTED_RISCV64_JAVA_VERSION=${EXPECTED_RISCV64_JAVA_VERSION:-11.0.31.28}
+    if [[ "$JAVA_VERSION" != "$EXPECTED_RISCV64_JAVA_VERSION" ]]; then
+        echo "Expected RISC-V Java $EXPECTED_RISCV64_JAVA_VERSION, got 
$JAVA_VERSION" >&2
+        exit 1
+    fi
+    if [[ "$JAVA_VM_NAME" != "OpenJDK 64-Bit Server VM" ]]; then
+        echo "Expected RISC-V Server VM, got $JAVA_VM_NAME" >&2
+        exit 1
+    fi
+    if [[ "$JAVA_VM_VENDOR" != "Alibaba" ]]; then
+        echo "Expected RISC-V Java vendor Alibaba, got $JAVA_VM_VENDOR" >&2
+        exit 1
+    fi
+    if [[ "$JAVA_VM_INFO" != *"mixed mode"* ]]; then
+        echo "Expected RISC-V Java mixed mode, got $JAVA_VM_INFO" >&2
+        exit 1
+    fi
+    if [[ "${LD_PRELOAD:-}" != *"libatomic.so.1"* ]]; then
+        echo "libatomic.so.1 was not added to LD_PRELOAD on riscv64" >&2
+        exit 1
+    fi
+    echo "LD_PRELOAD: $LD_PRELOAD"
+fi
+
+WORK_DIR=$(mktemp -d "${TMPDIR:-/tmp}/hugegraph-rocksdb-jni-smoke.XXXXXX")
+SMOKE_LOG="$WORK_DIR/rocksdb-jni-smoke.log"
+export ROCKSDB_SMOKE_DIR="$WORK_DIR/db"
+
+cleanup() {
+    rm -rf "$WORK_DIR"
+}
+trap cleanup EXIT
+
+"$JAVA_CMD" -cp "$SERVER_DIR/lib/*" groovy.ui.GroovyMain \
+            "$TRAVIS_DIR/rocksdb-jni-smoke.groovy" | tee "$SMOKE_LOG"
+
+if ! grep -q '^rocksdb-jni-smoke-ok$' "$SMOKE_LOG"; then
+    echo "RocksDB JNI smoke marker not found" >&2
+    exit 1
+fi
diff --git 
a/hugegraph-server/hugegraph-dist/src/assembly/travis/run-server-e2e-smoke-test.sh
 
b/hugegraph-server/hugegraph-dist/src/assembly/travis/run-server-e2e-smoke-test.sh
new file mode 100755
index 000000000..9762e4fa2
--- /dev/null
+++ 
b/hugegraph-server/hugegraph-dist/src/assembly/travis/run-server-e2e-smoke-test.sh
@@ -0,0 +1,191 @@
+#!/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.
+#
+set -euo pipefail
+
+if [[ $# -ne 3 || ( "$2" != "create" && "$2" != "verify" ) ]]; then
+    echo "USAGE: $0 SERVER_URL create|verify RUN_ID" >&2
+    exit 1
+fi
+
+SERVER_URL=${1%/}
+MODE=$2
+RUN_ID=$3
+
+if [[ ! "$RUN_ID" =~ ^[a-zA-Z0-9_]+$ ]]; then
+    echo "RUN_ID must contain only letters, numbers, and underscores" >&2
+    exit 1
+fi
+
+GRAPH_PATH=/graphspaces/DEFAULT/graphs/hugegraph
+WORK_DIR=$(mktemp -d "${TMPDIR:-/tmp}/hugegraph-server-smoke.XXXXXX")
+RESPONSE_FILE="$WORK_DIR/response.json"
+PROPERTY_KEY="riscv_smoke_name_$RUN_ID"
+VERTEX_LABEL="riscv_smoke_node_$RUN_ID"
+EDGE_LABEL="riscv_smoke_link_$RUN_ID"
+VERTEX_ONE="riscv-smoke-v1-$RUN_ID"
+VERTEX_TWO="riscv-smoke-v2-$RUN_ID"
+CURL_CONNECT_TIMEOUT=3
+CURL_PROBE_TIMEOUT=5
+CURL_REQUEST_TIMEOUT=60
+SERVER_READY_TIMEOUT=240
+
+cleanup() {
+    rm -rf "$WORK_DIR"
+}
+trap cleanup EXIT
+
+for command in curl jq; do
+    if ! command -v "$command" >/dev/null 2>&1; then
+        echo "Required command is unavailable: $command" >&2
+        exit 1
+    fi
+done
+
+if [[ -n "${HUGEGRAPH_USERNAME:-}" || -n "${HUGEGRAPH_PASSWORD:-}" ]]; then
+    if [[ -z "${HUGEGRAPH_USERNAME:-}" || -z "${HUGEGRAPH_PASSWORD:-}" ]]; then
+        echo "Set both HUGEGRAPH_USERNAME and HUGEGRAPH_PASSWORD" >&2
+        exit 1
+    fi
+fi
+
+curl_request() {
+    if [[ -n "${HUGEGRAPH_USERNAME:-}" ]]; then
+        curl --compressed --user "$HUGEGRAPH_USERNAME:$HUGEGRAPH_PASSWORD" "$@"
+    else
+        curl --compressed "$@"
+    fi
+}
+
+wait_for_server() {
+    local deadline=$((SECONDS + SERVER_READY_TIMEOUT))
+    while ((SECONDS < deadline)); do
+        if curl_request --silent --show-error --fail \
+                        --connect-timeout "$CURL_CONNECT_TIMEOUT" \
+                        --max-time "$CURL_PROBE_TIMEOUT" \
+                        "$SERVER_URL/versions" >/dev/null 2>&1; then
+            return 0
+        fi
+        sleep 1
+    done
+    echo "HugeGraph did not become ready at $SERVER_URL" >&2
+    return 1
+}
+
+request() {
+    local method=$1
+    local path=$2
+    local expected_status=$3
+    local body=${4:-}
+    local status
+    local curl_args=(--silent --show-error --output "$RESPONSE_FILE" \
+                     --write-out '%{http_code}' --request "$method" \
+                     --connect-timeout "$CURL_CONNECT_TIMEOUT" \
+                     --max-time "$CURL_REQUEST_TIMEOUT" \
+                     --header 'Content-Type: application/json')
+
+    if [[ -n "$body" ]]; then
+        curl_args+=(--data "$body")
+    fi
+    status=$(curl_request "${curl_args[@]}" "$SERVER_URL$path")
+    if [[ "$status" != "$expected_status" ]]; then
+        echo "$method $path returned HTTP $status, expected $expected_status" 
>&2
+        cat "$RESPONSE_FILE" >&2
+        return 1
+    fi
+}
+
+assert_json() {
+    local expression=$1
+    shift
+    if ! jq --exit-status "$@" "$expression" "$RESPONSE_FILE" >/dev/null; then
+        echo "JSON assertion failed: $expression" >&2
+        cat "$RESPONSE_FILE" >&2
+        return 1
+    fi
+}
+
+verify_graph() {
+    request GET "$GRAPH_PATH/graph/vertices/%22$VERTEX_ONE%22" 200
+    assert_json '.id == $id and .label == $label and .properties[$key] == 
"first"' \
+                --arg id "$VERTEX_ONE" --arg label "$VERTEX_LABEL" \
+                --arg key "$PROPERTY_KEY"
+
+    request GET "$GRAPH_PATH/graph/vertices/%22$VERTEX_TWO%22" 200
+    assert_json '.id == $id and .label == $label and .properties[$key] == 
"second"' \
+                --arg id "$VERTEX_TWO" --arg label "$VERTEX_LABEL" \
+                --arg key "$PROPERTY_KEY"
+
+    request GET "$GRAPH_PATH/graph/edges" 200
+    assert_json '.edges | any(.label == $label and .outV == $out and .inV == 
$in)' \
+                --arg label "$EDGE_LABEL" --arg out "$VERTEX_ONE" \
+                --arg in "$VERTEX_TWO"
+
+    request POST /gremlin 200 \
+        "$(jq -cn --arg query "g.V().hasLabel('$VERTEX_LABEL').count()" \
+             '{gremlin:$query, bindings:{}, language:"gremlin-groovy",
+               aliases:{g:"__g_DEFAULT-hugegraph"}}')"
+    assert_json '.result.data == [2]'
+}
+
+wait_for_server
+request GET /versions 200
+assert_json 'type == "object" and length > 0'
+
+if [[ "$MODE" == "create" ]]; then
+    request POST "$GRAPH_PATH/schema/propertykeys" 202 \
+        "$(jq -cn --arg name "$PROPERTY_KEY" \
+             '{name:$name, data_type:"TEXT", cardinality:"SINGLE", 
properties:[]}')"
+    assert_json '.property_key.name == $name and .task_id == 0' \
+                --arg name "$PROPERTY_KEY"
+
+    request POST "$GRAPH_PATH/schema/vertexlabels" 201 \
+        "$(jq -cn --arg name "$VERTEX_LABEL" --arg key "$PROPERTY_KEY" \
+             '{name:$name, id_strategy:"CUSTOMIZE_STRING", properties:[$key],
+               primary_keys:[], nullable_keys:[]}')"
+    assert_json '.name == $name' --arg name "$VERTEX_LABEL"
+
+    request POST "$GRAPH_PATH/schema/edgelabels" 201 \
+        "$(jq -cn --arg name "$EDGE_LABEL" --arg label "$VERTEX_LABEL" \
+             '{name:$name, source_label:$label, target_label:$label,
+               frequency:"SINGLE", properties:[], sort_keys:[], 
nullable_keys:[]}')"
+    assert_json '.name == $name' --arg name "$EDGE_LABEL"
+
+    request POST "$GRAPH_PATH/graph/vertices" 201 \
+        "$(jq -cn --arg id "$VERTEX_ONE" --arg label "$VERTEX_LABEL" \
+             --arg key "$PROPERTY_KEY" \
+             '{id:$id, label:$label, properties:{($key):"first"}}')"
+    assert_json '.id == $id' --arg id "$VERTEX_ONE"
+
+    request POST "$GRAPH_PATH/graph/vertices" 201 \
+        "$(jq -cn --arg id "$VERTEX_TWO" --arg label "$VERTEX_LABEL" \
+             --arg key "$PROPERTY_KEY" \
+             '{id:$id, label:$label, properties:{($key):"second"}}')"
+    assert_json '.id == $id' --arg id "$VERTEX_TWO"
+
+    request POST "$GRAPH_PATH/graph/edges" 201 \
+        "$(jq -cn --arg label "$EDGE_LABEL" --arg vertexLabel "$VERTEX_LABEL" \
+             --arg out "$VERTEX_ONE" --arg in "$VERTEX_TWO" \
+             '{label:$label, outVLabel:$vertexLabel, inVLabel:$vertexLabel,
+               outV:$out, inV:$in, properties:{}}')"
+    assert_json '.label == $label and .outV == $out and .inV == $in' \
+                --arg label "$EDGE_LABEL" --arg out "$VERTEX_ONE" \
+                --arg in "$VERTEX_TWO"
+fi
+
+verify_graph
+echo "server-e2e-smoke-$MODE-ok"
diff --git 
a/hugegraph-server/hugegraph-dist/src/main/resources/backend.properties 
b/hugegraph-server/hugegraph-dist/src/main/resources/backend.properties
index 45060f90c..119ee0244 100644
--- a/hugegraph-server/hugegraph-dist/src/main/resources/backend.properties
+++ b/hugegraph-server/hugegraph-dist/src/main/resources/backend.properties
@@ -15,4 +15,4 @@
 # limitations under the License.
 #
 
-backends=[rocksdb, hbase, hstore]
+backends=[${hugegraph.backends}]


Reply via email to