This is an automated email from the ASF dual-hosted git repository. hashutosh pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/hive.git
The following commit(s) were added to refs/heads/master by this push: new 2b177db HIVE-22737 : Concurrency: FunctionRegistry::getFunctionInfo is static object locked (Ashutosh Chauhan via Rajesh Balamohan) 2b177db is described below commit 2b177db2fd71ccd602247fae87362801a9095f1a Author: Ashutosh Chauhan <hashut...@apache.org> AuthorDate: Sat Apr 25 19:00:13 2020 -0700 HIVE-22737 : Concurrency: FunctionRegistry::getFunctionInfo is static object locked (Ashutosh Chauhan via Rajesh Balamohan) --- .../org/apache/hadoop/hive/ql/exec/Registry.java | 25 ++++++---------------- .../results/clientpositive/llap/udf_substr.q.out | 2 +- .../clientpositive/llap/udf_substring.q.out | 2 +- 3 files changed, 8 insertions(+), 21 deletions(-) diff --git a/ql/src/java/org/apache/hadoop/hive/ql/exec/Registry.java b/ql/src/java/org/apache/hadoop/hive/ql/exec/Registry.java index 40e9e97..6ceea2f 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/exec/Registry.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/Registry.java @@ -78,7 +78,7 @@ public class Registry { /** * The mapping from expression function names to expression classes. */ - private final Map<String, FunctionInfo> mFunctions = new LinkedHashMap<String, FunctionInfo>(); + private final Map<String, FunctionInfo> mFunctions = new ConcurrentHashMap<String, FunctionInfo>(); private final Set<Class<?>> builtIns = Collections.synchronizedSet(new HashSet<Class<?>>()); /** * Persistent map contains refcounts that are only modified in synchronized methods for now, @@ -91,6 +91,7 @@ public class Registry { /** * The epic lock for the registry. This was added to replace the synchronized methods with * minimum disruption; the locking should really be made more granular here. + * This lock is protecting mFunctions, builtIns and persistent maps. */ private final ReentrantLock lock = new ReentrantLock(); @@ -331,11 +332,9 @@ public class Registry { * @return */ public FunctionInfo getFunctionInfo(String functionName) throws SemanticException { - lock.lock(); - try { functionName = functionName.toLowerCase(); if (FunctionUtils.isQualifiedFunctionName(functionName)) { - FunctionInfo functionInfo = getQualifiedFunctionInfoUnderLock(functionName); + FunctionInfo functionInfo = getQualifiedFunctionInfo(functionName); addToCurrentFunctions(functionName, functionInfo); return functionInfo; } @@ -348,14 +347,10 @@ public class Registry { if (functionInfo == null) { functionName = FunctionUtils.qualifyFunctionName( functionName, SessionState.get().getCurrentDatabase().toLowerCase()); - functionInfo = getQualifiedFunctionInfoUnderLock(functionName); + functionInfo = getQualifiedFunctionInfo(functionName); } addToCurrentFunctions(functionName, functionInfo); return functionInfo; - } finally { - lock.unlock(); - } - } private void addToCurrentFunctions(String functionName, FunctionInfo functionInfo) { @@ -633,7 +628,7 @@ public class Registry { return null; } - private FunctionInfo getQualifiedFunctionInfoUnderLock(String qualifiedName) throws SemanticException { + private FunctionInfo getQualifiedFunctionInfo(String qualifiedName) throws SemanticException { FunctionInfo info = mFunctions.get(qualifiedName); if (info != null && info.isBlockedFunction()) { throw new SemanticException ("UDF " + qualifiedName + " is not allowed"); @@ -658,15 +653,7 @@ public class Registry { if (conf == null || !HiveConf.getBoolVar(conf, ConfVars.HIVE_ALLOW_UDF_LOAD_ON_DEMAND)) { return null; } - // This is a little bit weird. We'll do the MS call outside of the lock. Our caller calls us - // under lock, so we'd preserve the lock state for them; their finally block will release the - // lock correctly. See the comment on the lock field - the locking needs to be reworked. - lock.unlock(); - try { - return getFunctionInfoFromMetastoreNoLock(qualifiedName, conf); - } finally { - lock.lock(); - } + return getFunctionInfoFromMetastoreNoLock(qualifiedName, conf); } // should be called after session registry is checked diff --git a/ql/src/test/results/clientpositive/llap/udf_substr.q.out b/ql/src/test/results/clientpositive/llap/udf_substr.q.out index 00fa606..7c1a0f1 100644 --- a/ql/src/test/results/clientpositive/llap/udf_substr.q.out +++ b/ql/src/test/results/clientpositive/llap/udf_substr.q.out @@ -8,7 +8,7 @@ PREHOOK: type: DESCFUNCTION POSTHOOK: query: DESCRIBE FUNCTION EXTENDED substr POSTHOOK: type: DESCFUNCTION substr(str, pos[, len]) - returns the substring of str that starts at pos and is of length len orsubstr(bin, pos[, len]) - returns the slice of byte array that starts at pos and is of length len -Synonyms: mid, substring +Synonyms: substring, mid pos is a 1-based index. If pos<0 the starting position is determined by counting backwards from the end of str. Example: > SELECT substr('Facebook', 5) FROM src LIMIT 1; diff --git a/ql/src/test/results/clientpositive/llap/udf_substring.q.out b/ql/src/test/results/clientpositive/llap/udf_substring.q.out index d6b1c4a..7e96b79 100644 --- a/ql/src/test/results/clientpositive/llap/udf_substring.q.out +++ b/ql/src/test/results/clientpositive/llap/udf_substring.q.out @@ -8,7 +8,7 @@ PREHOOK: type: DESCFUNCTION POSTHOOK: query: DESCRIBE FUNCTION EXTENDED substring POSTHOOK: type: DESCFUNCTION substring(str, pos[, len]) - returns the substring of str that starts at pos and is of length len orsubstring(bin, pos[, len]) - returns the slice of byte array that starts at pos and is of length len -Synonyms: mid, substr +Synonyms: substr, mid pos is a 1-based index. If pos<0 the starting position is determined by counting backwards from the end of str. Example: > SELECT substring('Facebook', 5) FROM src LIMIT 1;