Jackie-Jiang commented on a change in pull request #5531: URL: https://github.com/apache/incubator-pinot/pull/5531#discussion_r437750886
########## File path: pinot-common/src/main/java/org/apache/pinot/common/function/FunctionRegistry.java ########## @@ -39,62 +38,63 @@ */ public class FunctionRegistry { private static final Logger LOGGER = LoggerFactory.getLogger(FunctionRegistry.class); - private static final Map<String, FunctionInfo> _functionInfoMap = new HashMap<>(); + private static final Map<String, FunctionInfo> FUNCTION_INFO_MAP = new HashMap<>(); + + private static boolean _initialized = false; /** - * Given a function name, asserts that a corresponding function was registered during construction and returns it + * Initializes the FunctionRegistry by registering the scalar functions via reflection. + * NOTE: In order to plugin methods using reflection, the methods should be inside a class that includes ".function." + * in its class path. This convention can significantly reduce the time of class scanning. */ - public static FunctionInfo getFunctionByName(String functionName) { - Preconditions.checkArgument(_functionInfoMap.containsKey(functionName.toLowerCase())); - return _functionInfoMap.get(functionName.toLowerCase()); + public static synchronized void init() { + if (_initialized) { + LOGGER.info("FunctionRegistry is already initialized"); + return; + } + + long startTimeMs = System.currentTimeMillis(); + Reflections reflections = new Reflections( + new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage("org.apache.pinot")) + .filterInputsBy(new FilterBuilder.Include(".*\\.function\\..*")) + .setScanners(new MethodAnnotationsScanner())); + Set<Method> methodSet = reflections.getMethodsAnnotatedWith(ScalarFunction.class); + for (Method method : methodSet) { + ScalarFunction scalarFunction = method.getAnnotation(ScalarFunction.class); + if (scalarFunction.enabled()) { + if (!scalarFunction.name().isEmpty()) { + FunctionRegistry.registerFunction(scalarFunction.name(), method); + } else { + FunctionRegistry.registerFunction(method); + } + } + } + LOGGER.info("Initialized FunctionRegistry within {}ms", System.currentTimeMillis() - startTimeMs); + _initialized = true; } /** - * Given a function name and a set of argument types, asserts that a corresponding function - * was registered during construction and returns it + * Registers a method with the name of the method. */ - public static FunctionInfo getFunctionByNameWithApplicableArgumentTypes(String functionName, - Class<?>[] argumentTypes) { - FunctionInfo functionInfo = getFunctionByName(functionName); - Preconditions.checkArgument(functionInfo.isApplicable(argumentTypes)); - return functionInfo; - } - - public static void registerFunction(Method method) { + public static synchronized void registerFunction(Method method) { registerFunction(method.getName().toLowerCase(), method); } - public static void registerFunction(String name, Method method) { + /** + * Registers a method with the given function name. + */ + public static synchronized void registerFunction(String functionName, Method method) { FunctionInfo functionInfo = new FunctionInfo(method, method.getDeclaringClass()); - _functionInfoMap.put(name, functionInfo); + FUNCTION_INFO_MAP.put(functionName, functionInfo); } - public static boolean containsFunctionByName(String funcName) { - return _functionInfoMap.containsKey(funcName.toLowerCase()); - } - - static { - try { - - Reflections reflections = new Reflections( - new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage("org.apache.pinot")) - .setScanners(new MethodAnnotationsScanner())); - - Set<Method> methodSet = reflections.getMethodsAnnotatedWith(ScalarFunction.class); - for (Method method : methodSet) { - ScalarFunction scalarFunction = method.getAnnotation(ScalarFunction.class); - if (scalarFunction.enabled()) { - if (!scalarFunction.name().isEmpty()) { - FunctionRegistry.registerFunction(scalarFunction.name(), method); - } else { - FunctionRegistry.registerFunction(method); - } - } - } - - } catch (Exception e) { - LOGGER.error("Caught exception when registering function", e); - throw new IllegalStateException(e); - } + /** + * Returns the {@link FunctionInfo} associated with the given function name, or {@code null} if there is no method + * registered under the name. This method should be called after the FunctionRegistry is initialized and all methods + * are already registered. + */ + @Nullable + public static FunctionInfo getFunctionByName(String functionName) { + return FUNCTION_INFO_MAP.get(functionName.toLowerCase()); Review comment: Added ---------------------------------------------------------------- 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. For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org For additional commands, e-mail: commits-h...@pinot.apache.org