TINKERPOP-1644
Use future instead of maintaining a separate map of failures.


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

Branch: refs/heads/TINKERPOP-1642
Commit: deb68280d986b086120d56a73659b1869c07a475
Parents: 13c93ca
Author: BrynCooke <brynco...@gmail.com>
Authored: Tue Mar 7 16:54:58 2017 +0000
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Fri Mar 10 11:12:36 2017 -0500

----------------------------------------------------------------------
 .../jsr223/GremlinGroovyScriptEngine.java       | 69 ++++++++------------
 1 file changed, 26 insertions(+), 43 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/deb68280/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java
----------------------------------------------------------------------
diff --git 
a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java
 
b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java
index a8365a2..67275f8 100644
--- 
a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java
+++ 
b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java
@@ -79,6 +79,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.ServiceLoader;
 import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Future;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
@@ -155,8 +157,7 @@ public class GremlinGroovyScriptEngine extends 
GroovyScriptEngineImpl
     /**
      * Script to generated Class map.
      */
-    private ManagedConcurrentValueMap<String, Class> classMap = new 
ManagedConcurrentValueMap<>(ReferenceBundle.getSoftBundle());
-    private ManagedConcurrentValueMap<String, CompilationFailedException> 
failedClassMap = new 
ManagedConcurrentValueMap<>(ReferenceBundle.getSoftBundle());
+    private ManagedConcurrentValueMap<String, Future<Class>> classMap = new 
ManagedConcurrentValueMap<>(ReferenceBundle.getSoftBundle());
 
     /**
      * Global closures map - this is used to simulate a single global 
functions namespace
@@ -533,56 +534,38 @@ public class GremlinGroovyScriptEngine extends 
GroovyScriptEngineImpl
         return makeInterface(thiz, clazz);
     }
 
-    private Class getScriptClassFromMap(String script) throws 
CompilationFailedException {
-        CompilationFailedException exception = failedClassMap.get(script);
-        if(exception != null) {
-            throw exception;
-        }
-        return classMap.get(script);
-
-    }
-
     Class getScriptClass(final String script) throws 
CompilationFailedException {
-        Class clazz = getScriptClassFromMap(script);
-        if (clazz != null) {
-            return clazz;
-        }
-        synchronized (this) {
-            clazz = getScriptClassFromMap(script);
+        Future<Class> clazz = classMap.get(script);
+
+        long start = System.currentTimeMillis();
+        try {
             if (clazz != null) {
-                return clazz;
+                return clazz.get();
             }
 
-            long start = System.currentTimeMillis();
-            try {
-                clazz = loader.parseClass(script, generateScriptName());
-                long time = System.currentTimeMillis() - start;
-                if(time > 5000) {
-                    //We warn if a script took longer than a few seconds. 
Repeatedly seeing these warnings is a sign that something is wrong.
-                    //Scripts with a large numbers of parameters often trigger 
this and should be avoided.
-                    log.warn("Script compilation {} took {}ms", script, time);
-                }
-                else {
-                    log.debug("Script compilation {} took {}ms", script, time);
-                }
-
+            clazz = CompletableFuture.supplyAsync(() -> 
loader.parseClass(script, generateScriptName()));
+            classMap.put(script, clazz);
+            return clazz.get();
 
-            }
-            catch(CompilationFailedException t) {
+        } catch (Exception e) {
+            if (e.getCause() instanceof CompilationFailedException) {
                 long finish = System.currentTimeMillis();
-                log.error("Script compilation FAILED {} took {}ms {}", script, 
finish - start, t);
-                failedClassMap.put(script, t);
-                throw t;
+                log.error("Script compilation FAILED {} took {}ms {}", script, 
finish - start, e.getCause());
+                throw (CompilationFailedException) e.getCause();
+            } else {
+                throw new AssertionError("Unexpected exception when compiling 
script", e);
             }
-            catch(Throwable t) {
-                long finish = System.currentTimeMillis();
-                log.error("Script compilation FAILED with throwable {} took 
{}ms {}", script, finish - start, t);
-                throw t;
+        } finally {
+            long time = System.currentTimeMillis() - start;
+            if (time > 5000) {
+                //We warn if a script took longer than a few seconds. 
Repeatedly seeing these warnings is a sign that something is wrong.
+                //Scripts with a large numbers of parameters often trigger 
this and should be avoided.
+                log.warn("Script compilation {} took {}ms", script, time);
+            } else {
+                log.debug("Script compilation {} took {}ms", script, time);
             }
-            classMap.put(script, clazz);
-
-            return clazz;
         }
+
     }
 
     boolean isCached(final String script) {

Reply via email to