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

yuqi4733 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new 2e2f79a1df [#9272] fix(lance-rest):Fix class absence for Gravitino 
Lance REST Server implementation (#9273)
2e2f79a1df is described below

commit 2e2f79a1dfb803f72aea0c1d36a70393f51dad24
Author: Mini Yu <[email protected]>
AuthorDate: Thu Nov 27 09:10:53 2025 +0800

    [#9272] fix(lance-rest):Fix class absence for Gravitino Lance REST Server 
implementation (#9273)
    
    ### What changes were proposed in this pull request?
    
    This pull request introduces a new bootstrap entry point for the Lance
    REST facade by adding the `GravitinoLanceRESTServer` class. This class
    is responsible for configuring, initializing, starting, joining, and
    stopping the Lance REST service, as well as managing the application
    lifecycle and shutdown hooks.
    
    New Lance REST server bootstrap:
    
    * Added the `GravitinoLanceRESTServer` class to serve as the main entry
    point for starting and managing the lifecycle of the Lance REST service,
    including configuration loading, component initialization, service
    startup, and graceful shutdown.
    ### Why are the changes needed?
    
    
    ### Why are the changes needed?
    
    It's a bug. It is caused by the fact that we need to include
    
https://github.com/apache/gravitino/commit/eb8ace8ae69e8bdda4bce207f09ab221bf29f48c
    before merging https://github.com/apache/gravitino/pull/9174
    
    Fix: #9272
    
    ### Does this PR introduce _any_ user-facing change?
    
    N/A.
    
    ### How was this patch tested?
    
    Test locally and using docker image.
---
 bin/gravitino-lance-rest-server.sh.template        | 206 +++++++++++++++++++++
 build.gradle.kts                                   |  77 +++++++-
 .../lance/server/GravitinoLanceRESTServer.java     | 107 +++++++++++
 3 files changed, 388 insertions(+), 2 deletions(-)

diff --git a/bin/gravitino-lance-rest-server.sh.template 
b/bin/gravitino-lance-rest-server.sh.template
new file mode 100644
index 0000000000..17f098903e
--- /dev/null
+++ b/bin/gravitino-lance-rest-server.sh.template
@@ -0,0 +1,206 @@
+#!/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 -ex
+USAGE="-e Usage: bin/gravitino-lance-rest-server.sh [--config <conf-dir>]\n\t
+        {start|run|stop|restart|status}"
+
+if [[ "$1" == "--config" ]]; then
+  shift
+  conf_dir="$1"
+  if [[ ! -d "${conf_dir}" ]]; then
+    echo "ERROR : ${conf_dir} is not a directory"
+    echo ${USAGE}
+    exit 1
+  else
+    export GRAVITINO_CONF_DIR="${conf_dir}"
+  fi
+  shift
+fi
+
+bin="$(dirname "${BASH_SOURCE-$0}")"
+bin="$(cd "${bin}">/dev/null; pwd)"
+
+. "${bin}/common.sh"
+
+check_java_version
+
+function check_process_status() {
+  local pid=$(found_lance_rest_server_pid)
+
+  if [[ -z "${pid}" ]]; then
+    echo "GravitinoLanceRESTServer is not running"
+  else
+    printArt
+    echo "GravitinoLanceRESTServer is running[PID:$pid]"
+  fi
+}
+
+function found_lance_rest_server_pid() {
+  process_name='GravitinoLanceRESTServer';
+  RUNNING_PIDS=$(ps x | grep ${process_name} | grep -v grep | awk '{print 
$1}');
+
+  if [[ -z "${RUNNING_PIDS}" ]]; then
+    return
+  fi
+
+  if ! kill -0 ${RUNNING_PIDS} > /dev/null 2>&1; then
+    echo "GravitinoLanceRESTServer running but process is dead"
+  fi
+
+  echo "${RUNNING_PIDS}"
+}
+
+function wait_for_lance_rest_server_to_die() {
+  timeout=10
+  timeoutTime=$(date "+%s")
+  let "timeoutTime+=$timeout"
+  currentTime=$(date "+%s")
+  forceKill=1
+
+  while [[ $currentTime -lt $timeoutTime ]]; do
+    local pid=$(found_lance_rest_server_pid)
+    if [[ -z "${pid}" ]]; then
+      forceKill=0
+      break
+    fi
+
+    kill ${pid} > /dev/null 2> /dev/null
+    if kill -0 ${pid} > /dev/null 2>&1; then
+      sleep 3
+    else
+      forceKill=0
+      break
+    fi
+    currentTime=$(date "+%s")
+  done
+
+  if [[ $forceKill -ne 0 ]]; then
+    kill -9 ${pid} > /dev/null 2> /dev/null
+  fi
+}
+
+function start() {
+  local pid=$(found_lance_rest_server_pid)
+
+  if [[ ! -z "${pid}" ]]; then
+    if kill -0 ${pid} >/dev/null 2>&1; then
+      echo "GravitinoLanceRESTServer is already running"
+      return 0;
+    fi
+  fi
+
+  if [[ ! -d "${GRAVITINO_LOG_DIR}" ]]; then
+    echo "Log dir doesn't exist, create ${GRAVITINO_LOG_DIR}"
+    mkdir -p "${GRAVITINO_LOG_DIR}"
+  fi
+
+  nohup ${JAVA_RUNNER} ${JAVA_OPTS} ${GRAVITINO_DEBUG_OPTS} -cp 
${GRAVITINO_CLASSPATH} ${GRAVITINO_SERVER_NAME} >> "${GRAVITINO_OUTFILE}" 2>&1 &
+
+  pid=$!
+  if [[ -z "${pid}" ]]; then
+    echo "GravitinoLanceRESTServer start error!"
+    return 1;
+  fi
+
+  sleep 2
+  check_process_status
+}
+
+function run() {
+  ${JAVA_RUNNER} ${JAVA_OPTS} ${GRAVITINO_DEBUG_OPTS} -cp 
${GRAVITINO_CLASSPATH} ${GRAVITINO_SERVER_NAME}
+}
+
+function stop() {
+  local pid
+
+  pid=$(found_lance_rest_server_pid)
+
+  if [[ -z "${pid}" ]]; then
+    echo "GravitinoLanceRESTServer is not running"
+  else
+    wait_for_lance_rest_server_to_die
+    echo "GravitinoLanceRESTServer stop"
+  fi
+}
+
+HOSTNAME=$(hostname)
+GRAVITINO_OUTFILE="${GRAVITINO_LOG_DIR}/gravitino-lance-rest-server.out"
+GRAVITINO_SERVER_NAME=org.apache.gravitino.lance.server.GravitinoLanceRESTServer
+GRAVITINO_SIMPLE_SERVER_NAME=gravitino-lance-rest-server
+
+JAVA_OPTS+=" -Dfile.encoding=UTF-8"
+JAVA_OPTS+=" 
-Dlog4j2.configurationFile=file://${GRAVITINO_CONF_DIR}/log4j2.properties"
+JAVA_OPTS+=" -Dgravitino.log.path=${GRAVITINO_LOG_DIR} ${GRAVITINO_MEM}"
+JAVA_OPTS+=" -Dgravitino.server.name=${GRAVITINO_SIMPLE_SERVER_NAME}"
+if [ "$JVM_VERSION" -eq 17 ]; then
+  JAVA_OPTS+=" -XX:+IgnoreUnrecognizedVMOptions"
+  JAVA_OPTS+=" --add-opens java.base/java.io=ALL-UNNAMED"
+  JAVA_OPTS+=" --add-opens java.base/java.lang.invoke=ALL-UNNAMED"
+  JAVA_OPTS+=" --add-opens java.base/java.lang.reflect=ALL-UNNAMED"
+  JAVA_OPTS+=" --add-opens java.base/java.lang=ALL-UNNAMED"
+  JAVA_OPTS+=" --add-opens java.base/java.math=ALL-UNNAMED"
+  JAVA_OPTS+=" --add-opens java.base/java.net=ALL-UNNAMED"
+  JAVA_OPTS+=" --add-opens java.base/java.nio=ALL-UNNAMED"
+  JAVA_OPTS+=" --add-opens java.base/java.text=ALL-UNNAMED"
+  JAVA_OPTS+=" --add-opens java.base/java.time=ALL-UNNAMED"
+  JAVA_OPTS+=" --add-opens java.base/java.util.concurrent.atomic=ALL-UNNAMED"
+  JAVA_OPTS+=" --add-opens java.base/java.util.concurrent=ALL-UNNAMED"
+  JAVA_OPTS+=" --add-opens java.base/java.util.regex=ALL-UNNAMED"
+  JAVA_OPTS+=" --add-opens java.base/java.util=ALL-UNNAMED"
+  JAVA_OPTS+=" --add-opens java.base/jdk.internal.ref=ALL-UNNAMED"
+  JAVA_OPTS+=" --add-opens java.base/jdk.internal.reflect=ALL-UNNAMED"
+  JAVA_OPTS+=" --add-opens java.sql/java.sql=ALL-UNNAMED"
+  JAVA_OPTS+=" --add-opens java.base/sun.util.calendar=ALL-UNNAMED"
+  JAVA_OPTS+=" --add-opens java.base/sun.nio.ch=ALL-UNNAMED"
+  JAVA_OPTS+=" --add-opens java.base/sun.nio.cs=ALL-UNNAMED"
+  JAVA_OPTS+=" --add-opens java.base/sun.security.action=ALL-UNNAMED"
+  JAVA_OPTS+=" --add-opens java.base/sun.util.calendar=ALL-UNNAMED"
+  JAVA_OPTS+=" --add-opens java.security.jgss/sun.security.krb5=ALL-UNNAMED"
+fi
+
+#JAVA_OPTS+=" -Djava.security.krb5.conf=/etc/krb5.conf"
+
+if [ -d "${GRAVITINO_HOME}/lance-rest-server/libs" ]; then
+  addJarInDir "${GRAVITINO_HOME}/lance-rest-server/libs"
+  addDirToClasspath "${GRAVITINO_HOME}/lance-rest-server/conf"
+else
+  addJarInDir "${GRAVITINO_HOME}/libs"
+fi
+
+case "${1}" in
+  start)
+    start
+    ;;
+  run)
+    run
+    ;;
+  stop)
+    stop
+    ;;
+  restart)
+    stop
+    start
+    ;;
+  status)
+    check_process_status
+    ;;
+  *)
+    echo ${USAGE}
+esac
diff --git a/build.gradle.kts b/build.gradle.kts
index d805b00002..be919c3c0d 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -773,6 +773,51 @@ tasks {
     }
   }
 
+  val compileLanceRESTServer by registering {
+    dependsOn("lance:lance-rest-server:copyLibAndConfigsToStandalonePackage")
+    group = "gravitino distribution"
+    
outputs.dir(projectDir.dir("distribution/${rootProject.name}-lance-rest-server"))
+    doLast {
+      copy {
+        from(projectDir.dir("conf")) {
+          include(
+            "${rootProject.name}-lance-rest-server.conf.template",
+            "${rootProject.name}-env.sh.template",
+            "log4j2.properties.template"
+          )
+          into("${rootProject.name}-lance-rest-server/conf")
+        }
+        from(projectDir.dir("bin")) {
+          include("common.sh.template", 
"${rootProject.name}-lance-rest-server.sh.template")
+          into("${rootProject.name}-lance-rest-server/bin")
+        }
+        into(outputDir)
+        rename { fileName ->
+          fileName.replace(".template", "")
+        }
+        eachFile {
+          if (name == "gravitino-env.sh") {
+            filter { line ->
+              line.replace("GRAVITINO_VERSION_PLACEHOLDER", "$version")
+            }
+          }
+        }
+        fileMode = 0b111101101
+      }
+
+      copy {
+        from(projectDir.dir("licenses")) { 
into("${rootProject.name}-lance-rest-server/licenses") }
+        from(projectDir.file("LICENSE.rest")) { 
into("${rootProject.name}-lance-rest-server") }
+        from(projectDir.file("NOTICE.rest")) { 
into("${rootProject.name}-lance-rest-server") }
+        from(projectDir.file("README.md")) { 
into("${rootProject.name}-lance-rest-server") }
+        into(outputDir)
+        rename { fileName ->
+          fileName.replace(".rest", "")
+        }
+      }
+    }
+  }
+
   val compileTrinoConnector by registering {
     dependsOn("trino-connector:trino-connector:copyLibs")
     group = "gravitino distribution"
@@ -792,7 +837,7 @@ tasks {
   }
 
   val assembleDistribution by registering(Tar::class) {
-    dependsOn("assembleTrinoConnector", "assembleIcebergRESTServer")
+    dependsOn("assembleTrinoConnector", "assembleIcebergRESTServer", 
"assembleLanceRESTServer")
     group = "gravitino distribution"
     finalizedBy("checksumDistribution")
     into("${rootProject.name}-$version-bin")
@@ -813,6 +858,17 @@ tasks {
     destinationDirectory.set(projectDir.dir("distribution"))
   }
 
+  val assembleLanceRESTServer by registering(Tar::class) {
+    dependsOn("compileLanceRESTServer")
+    group = "gravitino distribution"
+    finalizedBy("checksumLanceRESTServerDistribution")
+    into("${rootProject.name}-lance-rest-server-$version-bin")
+    from(compileLanceRESTServer.map { it.outputs.files.single() })
+    compression = Compression.GZIP
+    
archiveFileName.set("${rootProject.name}-lance-rest-server-$version-bin.tar.gz")
+    destinationDirectory.set(projectDir.dir("distribution"))
+  }
+
   val assembleIcebergRESTServer by registering(Tar::class) {
     dependsOn("compileIcebergRESTServer")
     group = "gravitino distribution"
@@ -840,9 +896,25 @@ tasks {
     }
   }
 
+  register("checksumLanceRESTServerDistribution") {
+    group = "gravitino distribution"
+    dependsOn(assembleLanceRESTServer)
+    val archiveFile = assembleLanceRESTServer.flatMap { it.archiveFile }
+    val checksumFile = archiveFile.map { archive ->
+      archive.asFile.let { it.resolveSibling("${it.name}.sha256") }
+    }
+    inputs.file(archiveFile)
+    outputs.file(checksumFile)
+    doLast {
+      checksumFile.get().writeText(
+        
serviceOf<ChecksumService>().sha256(archiveFile.get().asFile).toString()
+      )
+    }
+  }
+
   register("checksumDistribution") {
     group = "gravitino distribution"
-    dependsOn(assembleDistribution, "checksumTrinoConnector", 
"checksumIcebergRESTServerDistribution")
+    dependsOn(assembleDistribution, "checksumTrinoConnector", 
"checksumIcebergRESTServerDistribution", "checksumLanceRESTServerDistribution")
     val archiveFile = assembleDistribution.flatMap { it.archiveFile }
     val checksumFile = archiveFile.map { archive ->
       archive.asFile.let { it.resolveSibling("${it.name}.sha256") }
@@ -886,6 +958,7 @@ tasks {
         !it.name.startsWith("filesystem") &&
         !it.name.startsWith("flink") &&
         !it.name.startsWith("iceberg") &&
+        !it.name.startsWith("lance") &&
         !it.name.startsWith("spark") &&
         it.name != "hadoop-common" &&
         it.name != "hive-metastore-common" &&
diff --git 
a/lance/lance-rest-server/src/main/java/org/apache/gravitino/lance/server/GravitinoLanceRESTServer.java
 
b/lance/lance-rest-server/src/main/java/org/apache/gravitino/lance/server/GravitinoLanceRESTServer.java
new file mode 100644
index 0000000000..e28bdd5c17
--- /dev/null
+++ 
b/lance/lance-rest-server/src/main/java/org/apache/gravitino/lance/server/GravitinoLanceRESTServer.java
@@ -0,0 +1,107 @@
+/*
+ * 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.gravitino.lance.server;
+
+import org.apache.gravitino.Config;
+import org.apache.gravitino.GravitinoEnv;
+import org.apache.gravitino.lance.LanceRESTService;
+import org.apache.gravitino.lance.common.config.LanceConfig;
+import org.apache.gravitino.server.ServerConfig;
+import org.apache.gravitino.server.authentication.ServerAuthenticator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Bootstrap entry point for the Lance REST facade. */
+public class GravitinoLanceRESTServer {
+
+  private static final Logger LOG = 
LoggerFactory.getLogger(GravitinoLanceRESTServer.class);
+
+  public static final String CONF_FILE = "gravitino-lance-rest-server.conf";
+
+  private final Config serverConfig;
+
+  private LanceRESTService lanceRESTService;
+  private GravitinoEnv gravitinoEnv;
+
+  public GravitinoLanceRESTServer(Config config) {
+    this.serverConfig = config;
+    this.gravitinoEnv = GravitinoEnv.getInstance();
+    this.lanceRESTService = new LanceRESTService();
+  }
+
+  private void initialize() {
+    gravitinoEnv.initializeBaseComponents(serverConfig);
+    lanceRESTService.serviceInit(
+        serverConfig.getConfigsWithPrefix(LanceConfig.LANCE_CONFIG_PREFIX));
+    ServerAuthenticator.getInstance().initialize(serverConfig);
+  }
+
+  private void start() {
+    gravitinoEnv.start();
+    lanceRESTService.serviceStart();
+  }
+
+  private void join() {
+    lanceRESTService.join();
+  }
+
+  private void stop() throws Exception {
+    lanceRESTService.serviceStop();
+    LOG.info("Gravitino Lance REST service stopped");
+  }
+
+  public static void main(String[] args) {
+    LOG.info("Starting Gravitino Lance REST Server");
+    String confPath = System.getenv("GRAVITINO_TEST") == null ? "" : args[0];
+    ServerConfig serverConfig = ServerConfig.loadConfig(confPath, CONF_FILE);
+    GravitinoLanceRESTServer lanceRESTServer = new 
GravitinoLanceRESTServer(serverConfig);
+    lanceRESTServer.initialize();
+
+    try {
+      lanceRESTServer.start();
+    } catch (Exception e) {
+      LOG.error("Error while running lance REST server", e);
+      System.exit(-1);
+    }
+    LOG.info("Done, Gravitino Lance REST server started.");
+
+    Runtime.getRuntime()
+        .addShutdownHook(
+            new Thread(
+                () -> {
+                  try {
+                    
Thread.sleep(serverConfig.get(ServerConfig.SERVER_SHUTDOWN_TIMEOUT));
+                  } catch (InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                    LOG.error("Interrupted exception:", e);
+                  } catch (Exception e) {
+                    LOG.error("Error while running clean-up tasks in shutdown 
hook", e);
+                  }
+                }));
+    lanceRESTServer.join();
+
+    LOG.info("Shutting down Gravitino Lance REST Server ... ");
+    try {
+      lanceRESTServer.stop();
+      LOG.info("Gravitino Lance REST Server has shut down.");
+    } catch (Exception e) {
+      LOG.error("Error while stopping Gravitino Lance REST Server", e);
+    }
+  }
+}

Reply via email to