This is an automated email from the ASF dual-hosted git repository. rong pushed a commit to branch test-4 in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 053af93e1404d5fc661e775b4ed36f64fef1d403 Author: Steve Yurong Su <[email protected]> AuthorDate: Fri Jun 20 11:28:21 2025 +0800 move validation logic to ClusterConfigTaskExecutor.java --- .../iotdb/confignode/manager/UDFManager.java | 38 --------------------- .../config/executor/ClusterConfigTaskExecutor.java | 39 ++++++++++++++++++---- 2 files changed, 32 insertions(+), 45 deletions(-) diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/UDFManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/UDFManager.java index 59be1fd5a4f..00ed020a14e 100644 --- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/UDFManager.java +++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/UDFManager.java @@ -23,8 +23,6 @@ import org.apache.iotdb.common.rpc.thrift.TDataNodeLocation; import org.apache.iotdb.common.rpc.thrift.TSStatus; import org.apache.iotdb.commons.conf.IoTDBConstant; import org.apache.iotdb.commons.udf.UDFInformation; -import org.apache.iotdb.commons.udf.service.UDFClassLoader; -import org.apache.iotdb.commons.udf.service.UDFExecutableManager; import org.apache.iotdb.confignode.client.async.CnToDnAsyncRequestType; import org.apache.iotdb.confignode.client.async.CnToDnInternalServiceAsyncRequestManager; import org.apache.iotdb.confignode.client.async.handlers.DataNodeAsyncRequestContext; @@ -45,7 +43,6 @@ import org.apache.iotdb.mpp.rpc.thrift.TCreateFunctionInstanceReq; import org.apache.iotdb.mpp.rpc.thrift.TDropFunctionInstanceReq; import org.apache.iotdb.rpc.RpcUtils; import org.apache.iotdb.rpc.TSStatusCode; -import org.apache.iotdb.udf.api.UDF; import org.apache.tsfile.utils.Binary; import org.slf4j.Logger; @@ -92,13 +89,6 @@ public class UDFManager { new UDFInformation(udfName, req.getClassName(), false, isUsingURI, jarName, jarMD5); final boolean needToSaveJar = isUsingURI && udfInfo.needToSaveJar(jarName); - final TSStatus status = sandboxValidationBeforeCreateFunction(udfInformation); - if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) { - LOGGER.warn( - "Sandbox validation failed for UDF [{}], reason: {}", udfName, status.getMessage()); - return status; - } - LOGGER.info( "Start to create UDF [{}] on Data Nodes, needToSaveJar[{}]", udfName, needToSaveJar); @@ -131,34 +121,6 @@ public class UDFManager { } } - private TSStatus sandboxValidationBeforeCreateFunction(final UDFInformation udfInformation) { - try (final UDFClassLoader classLoader = - new UDFClassLoader(UDFExecutableManager.getInstance().getLibRoot())) { - // ensure that jar file contains the class and the class is a UDF - final Class<?> clazz = Class.forName(udfInformation.getClassName(), true, classLoader); - final UDF udf = (UDF) clazz.getDeclaredConstructor().newInstance(); - return udf.validate() - .map( - e -> - RpcUtils.getStatus( - TSStatusCode.UDF_LOAD_CLASS_ERROR, - String.format( - "Fail to validate UDF class [%s] for function [%s] in sandbox, reason: %s", - udfInformation.getClassName(), - udfInformation.getFunctionName(), - e.getMessage()))) - .orElse(RpcUtils.SUCCESS_STATUS); - } catch (final Throwable throwable) { - return RpcUtils.getStatus( - TSStatusCode.UDF_LOAD_CLASS_ERROR, - String.format( - "Fail to reflect or validate UDF class [%s] for function [%s] in sandbox, reason: %s", - udfInformation.getClassName(), - udfInformation.getFunctionName(), - throwable.getMessage())); - } - } - private List<TSStatus> createFunctionOnDataNodes(UDFInformation udfInformation, byte[] jarFile) throws IOException { final Map<Integer, TDataNodeLocation> dataNodeLocationMap = diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java index d2b5d0bbe77..4f4e7c7a27f 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java @@ -536,12 +536,37 @@ public class ClusterConfigTaskExecutor implements IConfigTaskExecutor { // ensure that jar file contains the class and the class is a UDF Class<?> clazz = Class.forName(createFunctionStatement.getClassName(), true, classLoader); UDF udf = (UDF) clazz.getDeclaredConstructor().newInstance(); - } catch (ClassNotFoundException - | NoSuchMethodException - | InstantiationException - | IllegalAccessException - | InvocationTargetException - | ClassCastException e) { + + final TSStatus maybeValidationFailed = + udf.validate() + .map( + e -> + RpcUtils.getStatus( + TSStatusCode.UDF_LOAD_CLASS_ERROR, + String.format( + "Fail to validate UDF class [%s] for function [%s] in sandbox, reason: %s", + createFunctionStatement.getClassName(), + createFunctionStatement.getUdfName(), + e.getMessage()))) + .orElse(RpcUtils.SUCCESS_STATUS); + if (maybeValidationFailed.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) { + LOGGER.warn( + "Failed to validate UDF class [{}] for function [{}] in sandbox, reason: {}", + createFunctionStatement.getClassName(), + createFunctionStatement.getUdfName(), + maybeValidationFailed.getMessage()); + future.setException( + new IoTDBException( + "Failed to validate UDF class '" + + createFunctionStatement.getClassName() + + "' for function '" + + createFunctionStatement.getUdfName() + + "', reason: " + + maybeValidationFailed.getMessage(), + maybeValidationFailed.getCode())); + return future; + } + } catch (Exception e) { LOGGER.warn( "Failed to create function when try to create UDF({}) instance first.", createFunctionStatement.getUdfName(), @@ -567,7 +592,7 @@ public class ClusterConfigTaskExecutor implements IConfigTaskExecutor { } else { future.set(new ConfigTaskResult(TSStatusCode.SUCCESS_STATUS)); } - } catch (ClientManagerException | IOException | TException e) { + } catch (Exception e) { future.setException(e); } return future;
