blob: 033e7c80dcc9d243bdb525ea98a31a29bf1315e4 [file] [log] [blame]
/*
* 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.drill.exec.store.sys;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.drill.exec.expr.fn.DrillFuncHolder;
import org.apache.drill.exec.expr.fn.FunctionImplementationRegistry;
import org.apache.drill.exec.expr.fn.FunctionLookupContext;
import org.apache.drill.exec.expr.fn.registry.FunctionHolder;
import org.apache.drill.exec.ops.ExecutorFragmentContext;
import org.apache.drill.exec.store.pojo.NonNullable;
/**
* List functions as a System Table
*/
public class FunctionsIterator implements Iterator<Object> {
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(FunctionsIterator.class);
private final Iterator<FunctionInfo> sortedIterator;
public FunctionsIterator(ExecutorFragmentContext context) {
Map<String, FunctionInfo> functionMap = new HashMap<String, FunctionInfo>();
//Access Registry for function list
FunctionLookupContext functionLookupContext = context.getFunctionRegistry();
//Check true instance type
if (functionLookupContext instanceof FunctionImplementationRegistry) {
FunctionImplementationRegistry functionImplRegistry = (FunctionImplementationRegistry) functionLookupContext;
Map<String, List<FunctionHolder>> jarFunctionListMap = functionImplRegistry.getAllJarsWithFunctionsHolders();
for (String jarName : jarFunctionListMap.keySet()) {
for (FunctionHolder dfhEntry : jarFunctionListMap.get(jarName)) {
populateFunctionMap(functionMap, jarName, dfhEntry.getHolder());
}
}
List<FunctionInfo> functionList = new ArrayList<FunctionsIterator.FunctionInfo>(functionMap.values());
functionList.sort((FunctionInfo o1, FunctionInfo o2) -> {
int result = o1.name.compareTo(o2.name);
if (result == 0) {
result = o1.signature.compareTo(o2.signature);
}
if (result == 0) {
return o1.returnType.compareTo(o2.returnType);
}
return result;
});
sortedIterator = functionList.iterator();
} else {
//Logging error
logger.error("Function Registry was found to be of {} instead of {}. No functions could be loaded ",
FunctionImplementationRegistry.class, functionLookupContext.getClass());
sortedIterator = Collections.emptyIterator();
}
}
/**
* Populate the map of functionInfo based on the functionSignatureKey for a given Jar-DrillFunctionHolder
* @param functionMap map to populate
* @param jarName name of the source jar
* @param dfh functionHolder that carries all the registered names and the signature
*/
private void populateFunctionMap(Map<String, FunctionInfo> functionMap, String jarName, DrillFuncHolder dfh) {
String registeredNames[] = dfh.getRegisteredNames();
String signature = dfh.getInputParameters();
String returnType = dfh.getReturnType().getMinorType().toString();
boolean isInternal = dfh.isInternal();
for (String name : registeredNames) {
//Generate a unique key for a function holder as 'functionName#functionSignature'
//Bumping capacity from default 16 to 64 (since key is expected to be bigger, and reduce probability of resizing)
String funcSignatureKey = new StringBuilder(64).append(name).append('#').append(signature).toString();
functionMap.put(funcSignatureKey, new FunctionInfo(name, signature, returnType, jarName, isInternal));
}
}
@Override
public boolean hasNext() {
return sortedIterator.hasNext();
}
@Override
public FunctionInfo next() {
return sortedIterator.next();
}
/**
* Representation of an entry in the System table - Functions
*/
public static class FunctionInfo {
@NonNullable
public final String name;
@NonNullable
public final String signature;
@NonNullable
public final String returnType;
@NonNullable
public final String source;
@NonNullable
public final boolean internal;
public FunctionInfo(String funcName, String funcSignature, String funcReturnType, String jarName) {
this(funcName, funcSignature, funcReturnType, jarName, false);
}
public FunctionInfo(String funcName, String funcSignature, String funcReturnType, String jarName, boolean isInternal) {
this.name = funcName;
this.signature = funcSignature;
this.returnType = funcReturnType;
this.source = jarName;
this.internal = isInternal;
}
}
}