[ https://issues.apache.org/jira/browse/DRILL-4726?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15468359#comment-15468359 ]
ASF GitHub Bot commented on DRILL-4726: --------------------------------------- Github user paul-rogers commented on a diff in the pull request: https://github.com/apache/drill/pull/574#discussion_r77705853 --- Diff: exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillFunctionRegistry.java --- @@ -218,4 +302,141 @@ private void registerOperatorsWithoutInference(DrillOperatorTable operatorTable) } } } + + /** + * Function registry holder. Stores function implementations by jar name, function name. + */ + private class GenericRegistryHolder<T, U> { + private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); + private final AutoCloseableLock readLock = new AutoCloseableLock(readWriteLock.readLock()); + private final AutoCloseableLock writeLock = new AutoCloseableLock(readWriteLock.writeLock()); + + // jar name, Map<function name, List<signature> + private final Map<T, Map<T, List<T>>> jars; + + // function name, Map<signature, function holder> + private final Map<T, Map<T, U>> functions; + + public GenericRegistryHolder() { + this.functions = Maps.newHashMap(); + this.jars = Maps.newHashMap(); + } + + public void addJar(T jName, Map<T, Pair<T, U>> sNameMap) { + try (AutoCloseableLock lock = writeLock.open()) { + Map<T, List<T>> map = jars.get(jName); + if (map != null) { + removeAllByJar(jName); + } + map = Maps.newHashMap(); + jars.put(jName, map); + + for (Entry<T, Pair<T, U>> entry : sNameMap.entrySet()) { + T sName = entry.getKey(); + Pair<T, U> pair = entry.getValue(); + addFunction(jName, pair.getKey(), sName, pair.getValue()); + } + } + } + + public void removeJar(T jName) { + try (AutoCloseableLock lock = writeLock.open()) { + removeAllByJar(jName); + } + } + + public List<T> getAllJarNames() { + try (AutoCloseableLock lock = readLock.open()) { + return Lists.newArrayList(jars.keySet()); + } + } + + public List<T> getAllFunctionNames(T jName) { + try (AutoCloseableLock lock = readLock.open()){ + Map<T, List<T>> map = jars.get(jName); + return map == null ? Lists.<T>newArrayList() : Lists.newArrayList(map.keySet()); + } + } + + public ListMultimap<T, U> getAllFunctionsWithHolders() { + try (AutoCloseableLock lock = readLock.open()) { + ListMultimap<T, U> multimap = ArrayListMultimap.create(); + for (Entry<T, Map<T, U>> entry : functions.entrySet()) { + multimap.putAll(entry.getKey(), Lists.newArrayList(entry.getValue().values())); + } + return multimap; + } + } + + public ListMultimap<T, T> getAllFunctionsWithSignatures() { + try (AutoCloseableLock lock = readLock.open()) { + ListMultimap<T, T> multimap = ArrayListMultimap.create(); + for (Entry<T, Map<T, U>> entry : functions.entrySet()) { + multimap.putAll(entry.getKey(), Lists.newArrayList(entry.getValue().keySet())); + } + return multimap; + } + } + + public List<U> getHoldersByFunctionName(T fName) { + try (AutoCloseableLock lock = readLock.open()) { + Map<T, U> map = functions.get(fName); + return map == null ? Lists.<U>newArrayList() : Lists.newArrayList(map.values()); + } + } + + public boolean containsJar(T jName) { + try (AutoCloseableLock lock = readLock.open()) { + return jars.containsKey(jName); + } + } + + public int functionsSize() { + try (AutoCloseableLock lock = readLock.open()) { + return functions.size(); + } + } + + private void addFunction(T jName, T fName, T sName, U fHolder) { + Map<T, List<T>> map = jars.get(jName); + + List<T> list = map.get(fName); + if (list == null) { + list = Lists.newArrayList(); + map.put(fName, list); + } + + if (!list.contains(sName)) { + list.add(sName); + + Map<T, U> sigsMap = functions.get(fName); + if (sigsMap == null) { + sigsMap = Maps.newHashMap(); + functions.put(fName, sigsMap); + } + + U u = sigsMap.get(sName); --- End diff -- Here U is a FuncHolder? We checked if the signature map already has a function associated with it and we ignore the new function if so. Is that the right behavior? Or, should an exception be thrown? If we throw an exception, should we clean up the partially-completed work for the current jar? Or, are we saying that the first function wins and subsequent identical signatures are silently ignored? In any case, we should document that policy in a comment. > Dynamic UDFs support > -------------------- > > Key: DRILL-4726 > URL: https://issues.apache.org/jira/browse/DRILL-4726 > Project: Apache Drill > Issue Type: New Feature > Affects Versions: 1.6.0 > Reporter: Arina Ielchiieva > Assignee: Arina Ielchiieva > Fix For: Future > > > Allow register UDFs without restart of Drillbits. > Design is described in document below: > https://docs.google.com/document/d/1FfyJtWae5TLuyheHCfldYUpCdeIezR2RlNsrOTYyAB4/edit?usp=sharing > -- This message was sent by Atlassian JIRA (v6.3.4#6332)