You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tajo.apache.org by ji...@apache.org on 2015/12/21 11:17:08 UTC

tajo git commit: TAJO-1997: Registering UDF, it needs to check duplication.

Repository: tajo
Updated Branches:
  refs/heads/master c577102ee -> 34508a76d


TAJO-1997: Registering UDF, it needs to check duplication.

Closes #883

Signed-off-by: Jihoon Son <ji...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/tajo/repo
Commit: http://git-wip-us.apache.org/repos/asf/tajo/commit/34508a76
Tree: http://git-wip-us.apache.org/repos/asf/tajo/tree/34508a76
Diff: http://git-wip-us.apache.org/repos/asf/tajo/diff/34508a76

Branch: refs/heads/master
Commit: 34508a76db5e846df8271d2c8ad3ab3275d2a33b
Parents: c577102
Author: Jongyoung Park <em...@gmail.com>
Authored: Mon Dec 21 19:15:56 2015 +0900
Committer: Jihoon Son <ji...@apache.org>
Committed: Mon Dec 21 19:16:49 2015 +0900

----------------------------------------------------------------------
 CHANGES                                         |  3 +
 .../org/apache/tajo/catalog/FunctionDesc.java   | 11 +++
 .../apache/tajo/function/FunctionSignature.java | 17 ++++
 .../org/apache/tajo/catalog/CatalogServer.java  | 11 +--
 .../apache/tajo/engine/eval/ExprTestBase.java   | 22 ++---
 .../engine/function/TestFunctionLoader.java     | 50 +++++++++++
 .../tajo/engine/function/FunctionLoader.java    | 89 ++++++++++++++------
 .../java/org/apache/tajo/master/TajoMaster.java | 19 +----
 .../java/org/apache/tajo/worker/TajoWorker.java |  2 +-
 9 files changed, 161 insertions(+), 63 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tajo/blob/34508a76/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index 51c1e62..5a8fa37 100644
--- a/CHANGES
+++ b/CHANGES
@@ -187,6 +187,9 @@ Release 0.12.0 - unreleased
 
   SUB TASKS
 
+    TAJO-1997: Registering UDF, it needs to check duplication.
+    (Contributed by Jongyoung Park. Committed by jihoon)
+
     TAJO-2024: Remove getContentSummary from HCatalogStore. (hyunsik)
 
     TAJO-2004: S3TableSpace needs to extend FileTableSpace. (jaehwa)

http://git-wip-us.apache.org/repos/asf/tajo/blob/34508a76/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FunctionDesc.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FunctionDesc.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FunctionDesc.java
index 5fa0c15..8c10418 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FunctionDesc.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FunctionDesc.java
@@ -157,6 +157,10 @@ public class FunctionDesc implements ProtoObject<FunctionDescProto>, Cloneable,
   public int hashCode() {
     return Objects.hashCode(signature);
   }
+
+  public int hashCodeWithoutType() {
+    return signature.hashCodeWithoutType();
+  }
   
   @Override
   public boolean equals(Object obj) {
@@ -167,6 +171,13 @@ public class FunctionDesc implements ProtoObject<FunctionDescProto>, Cloneable,
     }
     return false;
   }
+
+  public boolean equalsSignature(Object obj) {
+    if (obj instanceof FunctionDesc) {
+      return this.getSignature().equalsWithoutType(((FunctionDesc) obj).getSignature());
+    }
+    return false;
+  }
   
   @Override
   public Object clone() throws CloneNotSupportedException{

http://git-wip-us.apache.org/repos/asf/tajo/blob/34508a76/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionSignature.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionSignature.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionSignature.java
index 89ee017..ea4090f 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionSignature.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionSignature.java
@@ -144,4 +144,21 @@ public class FunctionSignature implements Comparable<FunctionSignature>, ProtoOb
 
     return o.paramTypes.length - paramTypes.length;
   }
+
+  public boolean equalsWithoutType(Object obj) {
+    if (obj instanceof FunctionSignature) {
+      FunctionSignature other = (FunctionSignature) obj;
+
+      boolean eq = name.equals(other.name);
+      eq = eq && TUtil.checkEquals(paramTypes, other.paramTypes);
+      eq = eq && returnType.equals(other.returnType);
+      return eq;
+    } else {
+      return false;
+    }
+  }
+
+  public int hashCodeWithoutType() {
+    return Objects.hashCode(name, returnType, Objects.hashCode(paramTypes));
+  }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/34508a76/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/CatalogServer.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/CatalogServer.java b/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/CatalogServer.java
index d649c5f..d99daee 100644
--- a/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/CatalogServer.java
+++ b/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/CatalogServer.java
@@ -95,13 +95,10 @@ public class CatalogServer extends AbstractService {
   private String bindAddressStr;
   final CatalogProtocolHandler handler;
 
-  private Collection<FunctionDesc> builtingFuncs;
+  private Collection<FunctionDesc> builtinFuncs;
 
   public CatalogServer() throws IOException {
-    super(CatalogServer.class.getName());
-    this.handler = new CatalogProtocolHandler();
-    this.linkedMetadataManager = new LinkedMetadataManager(Collections.EMPTY_LIST);
-    this.builtingFuncs = new ArrayList<>();
+    this(Collections.EMPTY_LIST, new ArrayList<>());
   }
 
   public CatalogServer(Collection<MetadataProvider> metadataProviders, Collection<FunctionDesc> sqlFuncs)
@@ -109,7 +106,7 @@ public class CatalogServer extends AbstractService {
     super(CatalogServer.class.getName());
     this.handler = new CatalogProtocolHandler();
     this.linkedMetadataManager = new LinkedMetadataManager(metadataProviders);
-    this.builtingFuncs = sqlFuncs;
+    this.builtinFuncs = sqlFuncs;
   }
 
   @Override
@@ -131,7 +128,7 @@ public class CatalogServer extends AbstractService {
 
       this.store = (CatalogStore) cons.newInstance(this.conf);
 
-      initBuiltinFunctions(builtingFuncs);
+      initBuiltinFunctions(builtinFuncs);
     } catch (Throwable t) {
       LOG.error("CatalogServer initialization failed", t);
       throw new TajoInternalError(t);

http://git-wip-us.apache.org/repos/asf/tajo/blob/34508a76/tajo-core-tests/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java
index 600a45f..602d566 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java
@@ -61,6 +61,7 @@ import org.junit.AfterClass;
 import org.junit.BeforeClass;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.TimeZone;
@@ -70,7 +71,7 @@ import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.junit.Assert.*;
 
 public class ExprTestBase {
-  private static TajoTestingCluster util;
+  private static TajoTestingCluster cluster;
   private static TajoConf conf;
   private static CatalogService cat;
   private static SQLAnalyzer analyzer;
@@ -88,28 +89,29 @@ public class ExprTestBase {
 
   @BeforeClass
   public static void setUp() throws Exception {
-    util = new TajoTestingCluster();
-    conf = util.getConfiguration();
-    util.startCatalogCluster();
-    cat = util.getCatalogService();
+    cluster = new TajoTestingCluster();
+    conf = cluster.getConfiguration();
+    cluster.startCatalogCluster();
+    cat = cluster.getCatalogService();
     cat.createTablespace(DEFAULT_TABLESPACE_NAME, "hdfs://localhost:1234/warehouse");
     cat.createDatabase(DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
-    Map<FunctionSignature, FunctionDesc> map = FunctionLoader.load();
-    map = FunctionLoader.loadUserDefinedFunctions(conf, map);
-    for (FunctionDesc funcDesc : map.values()) {
+    Map<FunctionSignature, FunctionDesc> map = FunctionLoader.loadBuiltinFunctions();
+    List<FunctionDesc> list = new ArrayList<>(map.values());
+    list.addAll(FunctionLoader.loadUserDefinedFunctions(conf));
+    for (FunctionDesc funcDesc : list) {
       cat.createFunction(funcDesc);
     }
 
     analyzer = new SQLAnalyzer();
     preLogicalPlanVerifier = new PreLogicalPlanVerifier(cat);
     planner = new LogicalPlanner(cat, TablespaceManager.getInstance());
-    optimizer = new LogicalOptimizer(util.getConfiguration(), cat, TablespaceManager.getInstance());
+    optimizer = new LogicalOptimizer(cluster.getConfiguration(), cat, TablespaceManager.getInstance());
     annotatedPlanVerifier = new LogicalPlanVerifier();
   }
 
   @AfterClass
   public static void tearDown() throws Exception {
-    util.shutdownCatalogCluster();
+    cluster.shutdownCatalogCluster();
   }
 
   private static void assertJsonSerDer(EvalNode expr) {

http://git-wip-us.apache.org/repos/asf/tajo/blob/34508a76/tajo-core-tests/src/test/java/org/apache/tajo/engine/function/TestFunctionLoader.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/function/TestFunctionLoader.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/function/TestFunctionLoader.java
index cf34c33..26f3262 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/function/TestFunctionLoader.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/function/TestFunctionLoader.java
@@ -19,16 +19,25 @@
 package org.apache.tajo.engine.function;
 
 import com.google.common.collect.Lists;
+import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.FunctionDesc;
+import org.apache.tajo.catalog.proto.CatalogProtos;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.exception.AmbiguousFunctionException;
+import org.apache.tajo.function.FunctionInvocation;
+import org.apache.tajo.function.FunctionSignature;
+import org.apache.tajo.function.FunctionSupplement;
 import org.apache.tajo.util.StringUtils;
 import org.junit.Test;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
 import static org.apache.tajo.LocalTajoTestingUtility.getResultText;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 
 public class TestFunctionLoader {
@@ -42,4 +51,45 @@ public class TestFunctionLoader {
     String result = getResultText(TestFunctionLoader.class, "testFindScalarFunctions.result");
     assertEquals(result.trim(), functionList.trim());
   }
+
+  @Test
+  public void testAmbiguousException() {
+    FunctionSignature signature = new FunctionSignature(CatalogProtos.FunctionType.GENERAL, "test1",
+        CatalogUtil.newSimpleDataType(TajoDataTypes.Type.TEXT),
+        CatalogUtil.newSimpleDataType(TajoDataTypes.Type.FLOAT8));
+
+    FunctionInvocation invocation = new FunctionInvocation();
+    FunctionSupplement supplement = new FunctionSupplement();
+
+    FunctionDesc desc = new FunctionDesc(signature, invocation, supplement);
+
+    List<FunctionDesc> builtins = new ArrayList<>();
+    builtins.add(desc);
+
+    signature = new FunctionSignature(CatalogProtos.FunctionType.GENERAL, "test2",
+        CatalogUtil.newSimpleDataType(TajoDataTypes.Type.INT8),
+        CatalogUtil.newSimpleDataType(TajoDataTypes.Type.INT8));
+
+    desc = new FunctionDesc(signature, invocation, supplement);
+    builtins.add(desc);
+
+    List<FunctionDesc> udfs = new ArrayList<>();
+
+    signature = new FunctionSignature(CatalogProtos.FunctionType.UDF, "test1",
+        CatalogUtil.newSimpleDataType(TajoDataTypes.Type.TEXT),
+        CatalogUtil.newSimpleDataType(TajoDataTypes.Type.FLOAT8));
+
+    desc = new FunctionDesc(signature, invocation, supplement);
+    udfs.add(desc);
+
+    boolean afexOccurs = false;
+
+    try {
+      FunctionLoader.mergeFunctionLists(builtins, udfs);
+    } catch (AmbiguousFunctionException e) {
+      afexOccurs = true;
+    }
+
+    assertTrue(afexOccurs);
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/34508a76/tajo-core/src/main/java/org/apache/tajo/engine/function/FunctionLoader.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/FunctionLoader.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/FunctionLoader.java
index 18baf0f..1fb5acf 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/function/FunctionLoader.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/FunctionLoader.java
@@ -28,7 +28,6 @@ import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.fs.FileStatus;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.fs.PathFilter;
 import org.apache.tajo.annotation.Nullable;
 import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.FunctionDesc;
@@ -37,6 +36,7 @@ import org.apache.tajo.conf.TajoConf;
 import org.apache.tajo.engine.function.annotation.Description;
 import org.apache.tajo.engine.function.annotation.ParamOptionTypes;
 import org.apache.tajo.engine.function.annotation.ParamTypes;
+import org.apache.tajo.exception.AmbiguousFunctionException;
 import org.apache.tajo.function.*;
 import org.apache.tajo.plan.function.python.PythonScriptEngine;
 import org.apache.tajo.util.ClassUtil;
@@ -46,6 +46,7 @@ import java.io.IOException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.*;
+import java.util.stream.Collectors;
 
 import static org.apache.tajo.catalog.proto.CatalogProtos.FunctionType.GENERAL;
 
@@ -59,7 +60,7 @@ public class FunctionLoader {
    *
    * @return
    */
-  public static Map<FunctionSignature, FunctionDesc> load() {
+  public static Map<FunctionSignature, FunctionDesc> loadBuiltinFunctions() {
     Map<FunctionSignature, FunctionDesc> map = Maps.newHashMap();
 
     List<FunctionDesc> dd = Lists.newArrayList();
@@ -87,13 +88,12 @@ public class FunctionLoader {
    * Load functions defined by users.
    *
    * @param conf
-   * @param functionMap
    * @return
    * @throws IOException
    */
-  public static Map<FunctionSignature, FunctionDesc> loadUserDefinedFunctions(TajoConf conf,
-                                                                              Map<FunctionSignature, FunctionDesc> functionMap)
+  public static List<FunctionDesc> loadUserDefinedFunctions(TajoConf conf)
       throws IOException {
+    List<FunctionDesc> functionList = new LinkedList<>();
 
     String[] codePaths = conf.getStrings(TajoConf.ConfVars.PYTHON_CODE_DIR.varname);
     if (codePaths != null) {
@@ -110,37 +110,27 @@ public class FunctionLoader {
 
         List<Path> filePaths = TUtil.newList();
         if (localFS.isDirectory(codePath)) {
-          for (FileStatus file : localFS.listStatus(codePath, new PathFilter() {
-            @Override
-            public boolean accept(Path path) {
-              return path.getName().endsWith(PythonScriptEngine.FILE_EXTENSION);
-            }
-          })) {
+          for (FileStatus file : localFS.listStatus(codePath,
+              (Path path) -> path.getName().endsWith(PythonScriptEngine.FILE_EXTENSION))) {
             filePaths.add(file.getPath());
           }
         } else {
           filePaths.add(codePath);
         }
         for (Path filePath : filePaths) {
-          for (FunctionDesc f : PythonScriptEngine.registerFunctions(filePath.toUri(),
-              FunctionLoader.PYTHON_FUNCTION_NAMESPACE)) {
-            functionMap.put(f.getSignature(), f);
-          }
+          PythonScriptEngine.registerFunctions(filePath.toUri(), FunctionLoader.PYTHON_FUNCTION_NAMESPACE).forEach(functionList::add);
         }
       }
     }
-    return functionMap;
+
+    return functionList;
   }
 
   public static Set<FunctionDesc> findScalarFunctions() {
     Set<FunctionDesc> functions = Sets.newHashSet();
 
-    Set<Method> scalarFunctions = findPublicStaticMethods("org.apache.tajo.engine.function", new Predicate() {
-      @Override
-      public boolean evaluate(Object object) {
-        return ((Method) object).getAnnotation(ScalarFunction.class) != null;
-      }
-    });
+    Set<Method> scalarFunctions = findPublicStaticMethods("org.apache.tajo.engine.function",
+        (Object object) -> ((Method) object).getAnnotation(ScalarFunction.class) != null);
 
     for (Method method : scalarFunctions) {
       ScalarFunction annotation = method.getAnnotation(ScalarFunction.class);
@@ -170,12 +160,8 @@ public class FunctionLoader {
   }
 
   private static Set<Class> findFunctionCollections(String packageName) {
-    return ClassUtil.findClasses(null, packageName, new Predicate() {
-      @Override
-      public boolean evaluate(Object object) {
-        return ((Class)object).getAnnotation(FunctionCollection.class) != null;
-      }
-    });
+    return ClassUtil.findClasses(null, packageName, (Object object) ->
+        ((Class)object).getAnnotation(FunctionCollection.class) != null);
   }
 
   private static Collection<FunctionDesc> buildFunctionDescs(ScalarFunction annotation, Method method) {
@@ -299,4 +285,51 @@ public class FunctionLoader {
 
     return sqlFuncs;
   }
+
+  public static Collection<FunctionDesc> loadFunctions(TajoConf conf) throws IOException, AmbiguousFunctionException {
+    List<FunctionDesc> functionList = new ArrayList<>(loadBuiltinFunctions().values());
+    List<FunctionDesc> udfs = loadUserDefinedFunctions(conf);
+
+    /* NOTE:
+     * For built-in functions, it is not done to check duplicates.
+     * There are two reasons.
+     * Firstly, it could be an useless operation in most of cases because built-in functions are not changed frequently
+     *   but checking will be done each startup.
+     * Secondly, this logic checks duplicate excluding type, but there are already duplicates in built-in functions
+     *   such as sum with/without 'distinct' feature. So to check duplicates in built-in functions, some other logic is needed.
+     * It should be another issue.
+     */
+    // merge lists and return it.
+    return mergeFunctionLists(functionList, udfs);
+  }
+
+  @SafeVarargs
+  static Collection<FunctionDesc> mergeFunctionLists(List<FunctionDesc> ... functionLists)
+      throws AmbiguousFunctionException {
+
+    Map<Integer, FunctionDesc> funcMap = new HashMap<>();
+    List<FunctionDesc> baseFuncList = functionLists[0];
+
+    // Build a map with a first list
+    for (FunctionDesc desc: baseFuncList) {
+      funcMap.put(desc.hashCodeWithoutType(), desc);
+    }
+
+    // Check duplicates for other function lists(should be UDFs practically)
+    for (int i=1; i<functionLists.length; i++) {
+      for (FunctionDesc desc: functionLists[i]) {
+        if (funcMap.containsKey(desc.hashCodeWithoutType())) {
+          FunctionDesc storedDesc = funcMap.get(desc.hashCodeWithoutType());
+          if (storedDesc.equalsSignature(desc)) {
+            throw new AmbiguousFunctionException(String.format("%s", storedDesc.toString()));
+          }
+        }
+
+        funcMap.put(desc.hashCodeWithoutType(), desc);
+        baseFuncList.add(desc);
+      }
+    }
+
+    return baseFuncList;
+  }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/34508a76/tajo-core/src/main/java/org/apache/tajo/master/TajoMaster.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/master/TajoMaster.java b/tajo-core/src/main/java/org/apache/tajo/master/TajoMaster.java
index 97e9613..91fba51 100644
--- a/tajo-core/src/main/java/org/apache/tajo/master/TajoMaster.java
+++ b/tajo-core/src/main/java/org/apache/tajo/master/TajoMaster.java
@@ -18,7 +18,6 @@
 
 package org.apache.tajo.master;
 
-import com.codahale.metrics.Gauge;
 import com.google.common.annotations.VisibleForTesting;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -36,7 +35,6 @@ import org.apache.hadoop.yarn.util.RackResolver;
 import org.apache.hadoop.yarn.util.SystemClock;
 import org.apache.tajo.catalog.CatalogServer;
 import org.apache.tajo.catalog.CatalogService;
-import org.apache.tajo.catalog.FunctionDesc;
 import org.apache.tajo.catalog.LocalCatalogWrapper;
 import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.catalog.proto.CatalogProtos.AlterTablespaceProto;
@@ -47,7 +45,6 @@ import org.apache.tajo.conf.TajoConf;
 import org.apache.tajo.conf.TajoConf.ConfVars;
 import org.apache.tajo.engine.function.FunctionLoader;
 import org.apache.tajo.exception.*;
-import org.apache.tajo.function.FunctionSignature;
 import org.apache.tajo.io.AsyncTaskService;
 import org.apache.tajo.master.rm.TajoResourceManager;
 import org.apache.tajo.metrics.ClusterResourceMetricSet;
@@ -77,8 +74,6 @@ import java.lang.management.ManagementFactory;
 import java.lang.management.ThreadInfo;
 import java.lang.management.ThreadMXBean;
 import java.net.InetSocketAddress;
-import java.util.Collection;
-import java.util.Map;
 
 import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
 import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
@@ -182,7 +177,7 @@ public class TajoMaster extends CompositeService {
     checkAndInitializeSystemDirectories();
     diagnoseTajoMaster();
 
-    catalogServer = new CatalogServer(TablespaceManager.getMetadataProviders(), loadFunctions());
+    catalogServer = new CatalogServer(TablespaceManager.getMetadataProviders(), FunctionLoader.loadFunctions(systemConf));
     addIfService(catalogServer);
     catalog = new LocalCatalogWrapper(catalogServer, systemConf);
 
@@ -220,21 +215,11 @@ public class TajoMaster extends CompositeService {
     LOG.info("Tajo Master is initialized.");
   }
 
-  private Collection<FunctionDesc> loadFunctions() throws IOException {
-    Map<FunctionSignature, FunctionDesc> functionMap = FunctionLoader.load();
-    return FunctionLoader.loadUserDefinedFunctions(systemConf, functionMap).values();
-  }
-
   private void initSystemMetrics() {
     systemMetrics = new TajoSystemMetrics(systemConf, Master.class, getMasterName());
     systemMetrics.start();
 
-    systemMetrics.register(Master.Cluster.UPTIME, new Gauge<Long>() {
-      @Override
-      public Long getValue() {
-        return context.getClusterUptime();
-      }
-    });
+    systemMetrics.register(Master.Cluster.UPTIME, () -> context.getClusterUptime());
 
     systemMetrics.register(Master.Cluster.class, new ClusterResourceMetricSet(context));
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/34508a76/tajo-core/src/main/java/org/apache/tajo/worker/TajoWorker.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/worker/TajoWorker.java b/tajo-core/src/main/java/org/apache/tajo/worker/TajoWorker.java
index 8315c1c..de337ae 100644
--- a/tajo-core/src/main/java/org/apache/tajo/worker/TajoWorker.java
+++ b/tajo-core/src/main/java/org/apache/tajo/worker/TajoWorker.java
@@ -199,7 +199,7 @@ public class TajoWorker extends CompositeService {
 
     historyReader = new HistoryReader(workerContext.getWorkerName(), this.systemConf);
 
-    FunctionLoader.loadUserDefinedFunctions(systemConf, new HashMap<>());
+    FunctionLoader.loadUserDefinedFunctions(systemConf);
 
     PythonScriptEngine.initPythonScriptEngineFiles();